<template>
	<view class="engineering-canvas" :bounces="false" :enhanced="true">
		<!-- 分层结构（叠加顺序） -->
		<canvas canvas-id="bgGrid" class="canvas-layer" style="z-index: 0" />
		<!-- 背景层 -->
		<canvas canvas-id="staticLines" class="canvas-layer" style="z-index: 0" />
		<!-- 永久线段层 -->
		<canvas canvas-id="addItemGroup" class="canvas-layer" style="z-index: 0" />
		<!-- 添加物品固定层 -->
		<canvas canvas-id="previewGroup" class="canvas-layer" style="z-index: 0" />
		<!-- 添加物品固定层 -->
		<canvas canvas-id="dynamicLayer" class="canvas-layer" @touchstart="handleTouchStart"
			@touchmove.prevent="handleTouchMove" @click="handleTap" @touchend="handleTouchEnd" style="z-index: 1" />
		<!-- 动态层 -->
		<cover-view style="position: absolute; right: 10rpx; top: 10rpx; z-index: 100" @click="subData">提交</cover-view>
		<cover-view style="position: absolute; right: 10rpx; top: 80rpx; z-index: 100"
			@click="exportData">导出</cover-view>
		<cover-view class="draw-oprate-btn" prevent-default>
			<cover-view class="close-btn" @click="closePic" v-if="waitCloseLine">
				合
			</cover-view>
		</cover-view>

		<cover-view class="data-operate" v-if="selectData" prevent-default>
			<template v-if="selectData.type == 'line' || selectData.type == 'arc'">
				<cover-view class="ope" @click="modData">
					<cover-view class="ope-icon">
						<cover-image src="https://renovationcdn.jiachuangnet.com/static/edit.png"></cover-image>
					</cover-view>
					<cover-view class="ope-name">编辑</cover-view>
				</cover-view>

				<cover-view class="ope" @click="convertToArc" v-if="selectData.type == 'line'">
					<cover-view class="ope-icon">
						<cover-image src="https://renovationcdn.jiachuangnet.com/static/arcLine.png"></cover-image>
					</cover-view>
					<cover-view class="ope-name">转弧线</cover-view>
				</cover-view>
				<cover-view class="ope" @click="convertToLine" v-if="selectData.type === 'arc'">
					<cover-view class="ope-icon">
						<cover-image src="https://renovationcdn.jiachuangnet.com/static/line.png"></cover-image>
					</cover-view>
					<cover-view class="ope-name">转直线</cover-view>
				</cover-view>
			</template>
			<cover-view class="ope" @click="rotateItem" v-else>
				<cover-view class="ope-icon">
					<cover-image src="https://renovationcdn.jiachuangnet.com/static/rotate.png"></cover-image>
				</cover-view>
				<cover-view class="ope-name">旋转</cover-view>
			</cover-view>
		</cover-view>

		<cover-view class="data-main-set" v-if="!!modMainData" prevent-default>
			<cover-view class="status-type-list">
				<cover-view class="single-status" :class="[statusSelect == 1 ? 'status-active' : '']"
					@click="statusSelect = 1">墙厚</cover-view>
				<cover-view class="single-status" :class="[statusSelect == 2 ? 'status-active' : '']"
					@click="statusSelect = 2">墙长</cover-view>
				<cover-view class="single-status" :class="[statusSelect == 3 ? 'status-active' : '']"
					@click="statusSelect = 3">属性</cover-view>
			</cover-view>

			<cover-view class="wall-thick" v-if="statusSelect == 1">
				<cover-view class="wall-thick-input">
					<cover-view>墙厚</cover-view>
					<cover-view>{{ inputNum ? inputNum : modMainData.lineHeight }}mm</cover-view>
				</cover-view>
			</cover-view>
			<cover-view class="wall-thick" v-if="statusSelect == 2">
				<cover-view class="wall-thick-input">
					<cover-view>墙长</cover-view>
					<cover-view>{{ inputNum ? inputNum : modMainData.lineWidth }}mm</cover-view>
				</cover-view>
			</cover-view>
			<cover-view class="wall-thick-calendar" v-if="statusSelect == 1 || statusSelect == 2">
				<cover-view class="cal-num">
					<cover-view class="single-num" @click="addNum(1)">
						<cover-view class="cal-btn">1</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(2)">
						<cover-view class="cal-btn">2</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(3)">
						<cover-view class="cal-btn">3</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(4)">
						<cover-view class="cal-btn">4</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(5)">
						<cover-view class="cal-btn">5</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(6)">
						<cover-view class="cal-btn">6</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(7)">
						<cover-view class="cal-btn">7</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(8)">
						<cover-view class="cal-btn">8</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(9)">
						<cover-view class="cal-btn">9</cover-view>
					</cover-view>
					<cover-view class="single-num" @click="addNum(0)" style="width: 100%">
						<cover-view class="cal-btn">0</cover-view>
					</cover-view>
				</cover-view>
				<cover-view class="cal-confirm">
					<cover-view class="cal-del">
						<cover-view class="cal-btn" @click="delNum" style="
                display: flex;
                align-items: center;
                justify-content: center;
              ">
							<cover-image src="https://renovationcdn.jiachuangnet.com/static/del.png"></cover-image>
						</cover-view>
					</cover-view>
					<cover-view class="cal-sure" style="flex: 1" @click="sureNum">
						<cover-view class="cal-btn"
							style="height: 100%; background: orange; color: #fff">确定</cover-view>
					</cover-view>
				</cover-view>
			</cover-view>
			<cover-view class="wall-list" v-if="statusSelect == 3" style="display: flex">
				<cover-view :class="[
            'wall',
            modMainData.wallType == 1 || !modMainData.wallType
              ? 'active-wall'
              : '',
          ]" @click="changeWall(1)">
					<cover-view class="wallPic">
						<cover-image src="https://renovationcdn.jiachuangnet.com/static/wallType1.png"
							style="width: 100%" mode="widthFix"></cover-image>
						<cover-image class="selected-wall"
							src="https://renovationcdn.jiachuangnet.com/static/selected.png"
							v-if="modMainData.wallType == 1 || !modMainData.wallType"></cover-image>
					</cover-view>
					<cover-view class="wallDesc"> 砌体墙 </cover-view>
				</cover-view>
				<cover-view :class="['wall', modMainData.wallType == 2 ? 'active-wall' : '']" @click="changeWall(2)">
					<cover-view class="wallPic">
						<cover-image src="https://renovationcdn.jiachuangnet.com/static/wallType2.png"
							style="width: 100%" mode="widthFix"></cover-image>
						<cover-image class="selected-wall"
							src="https://renovationcdn.jiachuangnet.com/static/selected.png"
							v-if="modMainData.wallType == 2"></cover-image>
					</cover-view>
					<cover-view class="wallDesc"> 剪力墙 </cover-view>
				</cover-view>
				<cover-view :class="['wall', modMainData.wallType == 3 ? 'active-wall' : '']" @click="changeWall(3)">
					<cover-view class="wallPic">
						<cover-image src="https://renovationcdn.jiachuangnet.com/static/wallType2.png"
							style="width: 100%" mode="widthFix"></cover-image>
						<cover-image class="selected-wall"
							src="https://renovationcdn.jiachuangnet.com/static/selected.png"
							v-if="modMainData.wallType == 3"></cover-image>
					</cover-view>
					<cover-view class="wallDesc"> 玻璃墙 </cover-view>
				</cover-view>
			</cover-view>
		</cover-view>
		<cover-view class="bot-btn-list" prevent-default>
			<cover-view class="bot-btn" @click="resetPoint" v-if="crossesIn">
				<cover-view class="btn-icon">
					<cover-image src="https://renovationcdn.jiachuangnet.com/static/reset.png"></cover-image>
				</cover-view>
				<cover-view>重置光标</cover-view>
			</cover-view>
			<cover-view class="bot-btn" prevent-default @touchstart.prevent="handleSetCrossStart"
				@touchmove.prevent="handleSetCrossMove" @touchend.prevent="handleSetCrossEnd" v-if="!crossesIn">
				<cover-view class="btn-icon">
					<cover-image src="https://renovationcdn.jiachuangnet.com/static/point.png"></cover-image>
				</cover-view>
				<cover-view>光标拖动到墙体</cover-view>
			</cover-view>
			<cover-view class="bot-btn" @click="addItems">
				<cover-view class="btn-icon">
					<cover-image src="https://renovationcdn.jiachuangnet.com/static/add.png"></cover-image>
				</cover-view>
				<!-- <cover-view>添加</cover-view> -->
			</cover-view>
		</cover-view>
		<cover-view v-if="addItemsShow" @click.prevent="addItemsShow = false"
			:style="{ height: addItemsShow ? '100%' : '0' }" style="
        width: 100%;
        height: 100%;
        background: transparent;
        position: fixed;
        left: 0;
        top: 0;
        z-index: 99;
      " @touchstart.prevent="touchStartAll" @touchmove.prevent="touchmoveAll" @touchend.prevent="touchEndAll">
			<cover-view class="add-item-list" prevent-default>
				<cover-view class="tab-scroll" scroll-x prevent-default>
					<cover-view class="tab-list" prevent-default>
						<cover-view :class="['tab-item', addItemType == 'door' ? 'active-item' : '']"
							@click.stop="addItemType = 'door'" prevent-default>
							门
						</cover-view>
						<cover-view :class="[
                'tab-item',
                addItemType == 'window' ? 'active-item' : '',
              ]" @click.stop="addItemType = 'window'" prevent-default>
							窗
						</cover-view>
						<cover-view :class="[
                'tab-item',
                addItemType == 'pillar' ? 'active-item' : '',
              ]" @click.stop="addItemType = 'pillar'" prevent-default>
							梁柱管
						</cover-view>
					</cover-view>
				</cover-view>
				<cover-view class="tab-item-main" prevent-default>
					<cover-view class="add-item" v-for="(data, idx) in addItemList[addItemType]" :key="idx"
						prevent-default @touchstart="(e) => handleAddItemStart(e, addItemType, data)">
						<cover-view class="add-inner" @click.stop="
                () => {
                  return false;
                }
              ">
							<cover-view class="add-item-icon">
								<template v-if="addItemType != 'window'">
									<cover-image
										:src="`https://renovationcdn.jiachuangnet.com/static/${addItemType}/${data.type}.png`"></cover-image>
								</template>
								<template v-else>
									<cover-image
										:src="`https://renovationcdn.jiachuangnet.com/static/window.png`"></cover-image>
								</template>
							</cover-view>
							<cover-view class="add-item-name">
								{{ data.name }}
							</cover-view>
						</cover-view>
					</cover-view>
				</cover-view>
			</cover-view>
		</cover-view>
	</view>
</template>

<script>
	const wxdata = wx.getSystemInfoSync();
	// 工业设计参数（匹配图像中的色调）
	let rafPending = false,
		scaleRafPending = false,
		dragRafPending = false;
	const gridSpacing = uni.upx2px(1); // 网格密度
	const crossColor = "#FF4444"; // 匹配图像红框
	const lineColor = "#333333"; // 深灰符合工业标准
	const previewColor = "#FF6600"; // 呼应橙色按钮
	const defaultScale = 40;
	let initialDistance = null;
	let addDoorPos = null;
	let addWindowPos = null;
	let addPillarPos = null;
	// 上下文实例
	let bgCtx = null,
		staticCtx = null,
		dynamicCtx = null,
		addItemGroupCtx = null,
		previewGroupCtx = null;
	let lines = [];
	let doors = [];
	let windowList = [];
	let pillarList = [];
	let activeCross = null,
		originPos = null;
	let sureRoom = [];
	let controlArcLine = null;
	let animationFrameHandle = null;
	initialDistance = null;
	let scaleCenter = null;
	const distance = (p1, p2) => Math.sqrt((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2);
	export default {
		data() {
			return {
				addData: null,
				defaultData: null,
				focusLine: null,
				crossesIn: true,
				previewCross: true,
				isSettingCross: true,
				addItemType: "door",
				statusSelect: 1,
				inputNum: null,
				addItemList: {
					door: [{
							type: 1,
							name: "普通门",
							width: 40,
						},
						{
							type: 2,
							name: "双开门",
							width: 80,
						},
					],
					window: [{
						type: 1,
						name: "普通窗",
						width: 80,
						height: 10,
					}, ],
					pillar: [{
							type: 1,
							name: "方柱",
							width: 80,
							height: 80,
						},
						{
							type: 2,
							name: "圆柱",
							width: 80,
						},
					],
				},
				crosses: [{
					x: 0, // 使用世界坐标原点
					y: 0,
				}, ],
				viewport: {
					offsetX: wxdata.windowWidth / 2, // 初始偏移设为屏幕中心
					offsetY: wxdata.windowHeight / 2,
					scale: defaultScale,
				},
				isDragging: false,
				dragStart: {
					x: 0,
					y: 0,
				},
				selectData: null,
				modMainData: null,
				addItemsShow: null,
				waitCloseLine: null,
			};
		},
		onLoad(options) {
			if (options.id) {
				this.getData(options.id);
			}
		},
		onShow() {
			// 初始化三层上下文
			bgCtx = uni.createCanvasContext("bgGrid", {
				devicePixelRatio: 1,
			});
			staticCtx = uni.createCanvasContext("staticLines");
			dynamicCtx = uni.createCanvasContext("dynamicLayer");
			addItemGroupCtx = uni.createCanvasContext("addItemGroup");
			previewGroupCtx = uni.createCanvasContext("previewGroup");
			// 分层渲染（保证视觉层级）
			staticCtx.imageSmoothingEnabled = true;
			bgCtx.imageSmoothingEnabled = true;
			bgCtx.imageSmoothingEnabled = true;
			addItemGroupCtx.imageSmoothingEnabled = true;
			previewGroupCtx.imageSmoothingEnabled = true;
			this.drawBackground();
			this.drawStaticLines();
			this.drawDynamicLayer();
		},
		methods: {
			touchStartAll(e) {},
			touchmoveAll(e) {
				if (this.addData) {
					this.handleAddItemMove(e, this.addData.classType, this.addData.data);
				}
			},
			touchEndAll(e) {
				if (this.addData) {
					this.handleAddItemEnd(e, this.addData.classType, this.addData.data);
				}
			},
			exportData() {
				uni.request({
					url: "http://120.76.159.210:9439/cl/cad/dxf/" + this.defaultData.id,
					method: "GET",
					success(res) {
						uni.downloadFile({
							url: "http://yypt.hxjykt.com/cad/dxf/1751047932948.dxf",
							success(res) {
								uni.openDocument({
									filePath: res.tempFilePath,
									fileType: "other",
									success: () => {
										console.log("文件已打开，用户可手动保存");
									},
									fail: (err) => {
										console.error("打开失败:", err);
										uni.showToast({
											title: "打开失败",
											icon: "none",
										});
									},
								});
								// uni.saveFile({
								// 	tempFilePath: res.tempFilePath,
								// 	success(file) {

								// 		uni.showToast({
								// 			icon: 'none',
								// 			mask: true,
								// 			title: '文件已保存：' + file.savedFilePath, //保存路径
								// 			duration: 3000,
								// 		});

								// 	}
								// })
							},
						});
					},
				});
			},
			getData(id) {
				const that = this;
				uni.request({
					url: "http://120.76.159.210:9439/cl/cad/" + id,
					method: "GET",
					success(res) {
						if (res.data.data) {
							that.defaultData = res.data.data;
							// 墙
							const sureRoomList = that.defaultData.drawCadInfos
								.find((item) => item.drawType == 1)
								?.drawCadDetails.map((item) => {
									item.drawStr = JSON.parse(item.drawStr);
									return item;
								});
							// console.log(sureRoomList)
							sureRoom[0] = sureRoomList.map((item, idx) => {
								// const startPoint = that.snapToGrid(item.start.x, item.start.y);
								// const formatStart = that.screenToWorld({x:startPoint.x,y:startPoint.y})
								// const endPoint = that.snapToGrid(item.end.x, item.end.y)
								// const formatEnd = that.screenToWorld({x:endPoint.x,y:endPoint.y})
								const newLine = {
									start: item.drawStr.start,
									end: item.drawStr.end,
									idx: idx + 1,
									lineHeight: item.width,
									type: "line",
								};
								return newLine;
							});
							console.log(sureRoom[0]);
							// 门
							const singleDoor = that.defaultData.drawCadInfos
								.find((item) => item.drawType == 2)
								.drawCadDetails.map((item) => {
									item.type = 1;
									return item;
								});
							const doubleDoor = that.defaultData.drawCadInfos
								.find((item) => item.drawType == 3)
								.drawCadDetails.map((item) => {
									item.type = 2;
									return item;
								});
							doors = [...singleDoor, ...doubleDoor].map((item, idx) => {
								const doorList = [];
								const point = that.snapToGrid(item.x, item.y);
								const door = {
									...item,
									width: item.type == 1 ? item.radius : item.radius * 2,
									pos: that.screenToWorld({
										x: point.x,
										y: point.y,
									}),
									rotateDeg: 360 - item.rotationDirection,
									idx,
									class: "door",
								};
								return door;
							});
							// 窗
							const windowGroup = that.defaultData.drawCadInfos.find(
								(item) => item.drawType == 6
							).drawCadDetails;
							windowList = windowGroup.map((item, idx) => {
								const point = that.snapToGrid(item.x, item.y);
								const windowData = {
									type: 1,
									name: "普通窗",
									width: item.width,
									height: item.height,
									pos: that.screenToWorld({
										x: point.x,
										y: point.y,
									}),
									idx: idx,
									class: "window",
								};
								return windowData;
							});

							const rectPillar = that.defaultData.drawCadInfos
								.find((item) => item.drawType == 4)
								.drawCadDetails.map((item) => {
									item.type = 1;
									return item;
								});
							const cirPillar = that.defaultData.drawCadInfos
								.find((item) => item.drawType == 5)
								.drawCadDetails.map((item) => {
									item.type = 2;
									return item;
								});
							pillarList = [...rectPillar, ...cirPillar].map((item, idx) => {
								const point = that.snapToGrid(item.x, item.y);
								const pillar = {
									...item,
									width: item.type == 1 ? item.width : item.radius * 2,
									height: item.type == 1 ? item.height : null,
									idx,
									pos: that.screenToWorld({
										x: point.x,
										y: point.y,
									}),
									class: "pillar",
								};
								return pillar;
							});

							that.drawStaticLines();
							that.drawAddItem();
						}
					},
				});
			},

			subData() {
				if (!sureRoom || !sureRoom.length) {
					return;
				}
				const that = this;
				const {
					area
				} = this.calculatePolygonArea(sureRoom[0]);
				const natArea = area * this.viewport.scale ** 2;
				let pillarArea = 0;
				const subParams = [{
						drawType: 1,
						drawInfos: sureRoom[0]?.map((item) => {
							let obj = {};
							const worldPosStart = that.worldToScreen({
								x: item.start.x,
								y: item.start.y,
							});
							const worldPosEnd = that.worldToScreen({
								x: item.end.x,
								y: item.end.y,
							});
							if (worldPosStart.y == worldPosEnd.y) {
								obj.wallType = 2;
							} else {
								obj.wallType = 1;
							}
							obj.drawStr = JSON.stringify({
								start: item.start,
								end: item.end,
							});
							obj.x =
								worldPosStart.x > worldPosEnd.x ? worldPosEnd.x : worldPosStart.x;
							obj.y =
								worldPosStart.y > worldPosEnd.y ? worldPosEnd.y : worldPosStart.y;
							obj.height = distance(worldPosStart, worldPosEnd);
							obj.width = item.lineHeight;
							obj.radius = 0;
							obj.angle = 0;
							obj.areaNum = 0;
							obj.floorCount = 0;
							obj.floorArea = 0;
							return obj;
						}),
					},
					{
						drawType: 2,
						drawInfos: doors
							?.filter((item) => item.type == 1)
							?.map((item) => {
								const worldPosStart = that.worldToScreen({
									x: item.pos.x,
									y: item.pos.y,
								});
								// item.width=0
								let obj = {};
								obj.x = worldPosStart.x;
								obj.y = worldPosStart.y;
								obj.height = item.width;
								obj.width = 0;
								obj.radius = item.width;
								obj.angle = 90;
								obj.rotationDirection = 360 - (item.rotateDeg || 0);
								obj.areaNum = 0;
								obj.floorCount = 0;
								obj.floorArea = 0;
								return obj;
							}),
					},
					{
						drawType: 3,
						drawInfos: doors
							?.filter((item) => item.type == 2)
							?.map((item) => {
								console.log(item);
								let obj = {};
								const worldPosStart = that.worldToScreen({
									x: item.pos.x,
									y: item.pos.y,
								});
								obj.x = worldPosStart.x;
								obj.y = worldPosStart.y;
								if (!item.rotateDeg || item.rotateDeg == 360) {
									obj.rotationDirection = 360;
									obj.angle = 90;
									obj.x = obj.x + item.width / 2;
								} else if (item.rotateDeg == 90) {
									obj.rotationDirection = 270;
									obj.angle = 360;
									obj.x = obj.y + item.width / 2;
								} else if (item.rotateDeg == 180) {
									obj.angle = 180;
									obj.rotationDirection = 270;
									obj.x = obj.x + item.width / 2;
								} else {
									obj.angle = 90;
									obj.rotationDirection = 180;
									obj.x = obj.y - item.width / 2;
								}

								obj.height = item.width / 2;
								obj.width = 0;
								obj.radius = item.width / 2;
								// obj.angle = item.rotateDeg || 0;
								obj.areaNum = 0;
								obj.floorCount = 0;
								obj.floorArea = 0;
								return obj;
							}),
					},
					{
						drawType: 4,
						drawInfos: pillarList
							?.filter((item) => item.type == 1)
							?.map((item) => {
								let obj = {};
								const worldPosStart = that.worldToScreen({
									x: item.pos.x,
									y: item.pos.y,
								});
								obj.x = worldPosStart.x - item.width / 2;
								obj.y = worldPosStart.y - item.height / 2;
								obj.height = item.height;
								obj.width = item.width;
								obj.radius = 0;
								obj.angle = 0;
								obj.areaNum = 0;
								obj.floorCount = 0;
								obj.floorArea = item.width * item.height;
								pillarArea += item.width * item.height;
								return obj;
							}),
					},
					{
						drawType: 5,
						drawInfos: pillarList
							?.filter((item) => item.type == 2)
							?.map((item) => {
								let obj = {};
								const worldPosStart = that.worldToScreen({
									x: item.pos.x,
									y: item.pos.y,
								});
								obj.x = worldPosStart.x;
								obj.y = worldPosStart.y;
								obj.height = 0;
								obj.width = 0;
								obj.radius = item.width / 2;
								obj.angle = 0;
								obj.areaNum = 0;
								obj.floorCount = 0;
								obj.floorArea = Math.PI * Math.pow(item.width / 2, 2);
								pillarArea += Math.PI * Math.pow(item.width / 2, 2);
								return obj;
							}),
					},
					{
						drawType: 6,
						drawInfos: windowList?.map((item) => {
							console.log(item);
							let obj = {};
							const worldPosStart = that.worldToScreen({
								x: item.pos.x,
								y: item.pos.y,
							});
							if (item.rotateDeg == 90 || item.rotateDeg == 270) {
								obj.x = worldPosStart.x;
								obj.y = worldPosStart.y - item.width / 2;
								obj.height = item.width;
								obj.width = item.height;
							} else {
								obj.x = worldPosStart.x - item.width / 2;
								obj.y = worldPosStart.y;
								obj.height = item.height;
								obj.width = item.width;
							}

							obj.radius = 0;
							obj.angle = 0;
							obj.areaNum = 0;
							obj.floorCount = 0;
							obj.floorArea = 0;
							return obj;
						}),
					},
				];
				// console.log(JSON.stringify(subParams));
				const formatData = {
					name: "123456",
					userId: 111111,
					info: subParams,
					areaNum: natArea, //总面积
					floorCount: 1.3, //地板数量
					floorArea: (natArea - pillarArea) / 0.64, //地板面积
				};
				console.log(JSON.stringify(formatData));
				if (!this.defaultData) {
					uni.request({
						url: "http://120.76.159.210:9439/cl/cad",
						method: "post",
						data: formatData,
						success: function(res) {
							if (res.data.success) {
								uni.showToast({
									title: "新增成功",
									type: "success",
								});
								setTimeout(function() {
									uni.navigateBack();
								}, 1000);
							}
							// else{
							// 	uni.showToast({
							// 		title:'失败',
							// 		type:'error'
							// 	})
							// }
						},
						fail: function(res) {},
					});
				} else {
					uni.request({
						url: "http://120.76.159.210:9439/cl/cad/" + this.defaultData.userId,
						method: "PUT",
						data: formatData,
						success: function(res) {
							if (res.data.success) {
								uni.showToast({
									title: "编辑成功",
									type: "success",
								});
								setTimeout(function() {
									uni.navigateBack();
								}, 1000);
							} else {
								uni.showToast({
									title: "失败",
									type: "error",
								});
							}
						},
						fail: function(res) {},
					});
				}
			},
			rotateItem() {
				previewGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);

				if (!this.selectData.rotateDeg || this.selectData.rotateDeg == 360) {
					this.selectData.rotateDeg = 90;
				} else {
					this.selectData.rotateDeg += 90;
				}
				if (this.selectData.class == "door") {
					doors[this.selectData.idx] = this.selectData;
					this.drawDoor(this.selectData, previewGroupCtx);
				} else if (this.selectData.class == "window") {
					windowList[this.selectData.idx] = this.selectData;
					this.drawWindow(this.selectData, previewGroupCtx);
				} else {
					pillarList[this.selectData.idx] = this.selectData;
					this.drawPillar(this.selectData, previewGroupCtx);
				}
				this.drawControlPoints(this.selectData);
			},
			delNum() {
				if (this.inputNum === null) {
					this.inputNum = "";
				}
				let data = String(this.inputNum);

				if (data && data.length > 0) {
					data = data.substr(data.length - 1 - 1, 1);
					this.inputNum = data;
				}
			},
			addNum(num) {
				if (!this.inputNum) {
					this.inputNum = num;
				} else {
					this.inputNum += String(num);
				}
			},
			sureNum() {
				// this.modMainData
				if (!this.inputNum) {
					this.inputNum = null;
					return;
				}
				if (this.statusSelect == 1) {
					this.modMainData.lineHeight = Number(this.inputNum);
				} else if (this.statusSelect == 2) {
					const oldLength = this.modMainData.lineWidth;
					const newLength = Number(this.inputNum);
					const ratio = newLength / oldLength;

					// 计算原始向量
					const dx = this.modMainData.end.x - this.modMainData.start.x;
					const dy = this.modMainData.end.y - this.modMainData.start.y;

					// 计算新的终点位置
					const newEndX = this.modMainData.start.x + dx * ratio;
					const newEndY = this.modMainData.start.y + dy * ratio;

					// 计算位置偏移量
					const offsetX = newEndX - this.modMainData.end.x;
					const offsetY = newEndY - this.modMainData.end.y;

					// 更新当前墙的终点
					this.modMainData.end = {
						x: newEndX,
						y: newEndY,
					};

					// 更新弧线控制点（如果有）
					if (this.modMainData.type === "arc" && this.modMainData.controlPoint) {
						this.modMainData.controlPoint = {
							x: this.modMainData.controlPoint.x * ratio,
							y: this.modMainData.controlPoint.y * ratio,
						};
					}

					this.modMainData.lineWidth = newLength;

					// 更新后续所有墙的位置
					if (this.modMainData.idx < lines.length - 1) {
						for (let i = this.modMainData.idx + 1; i < lines.length; i++) {
							// 移动后续墙的起点和终点
							lines[i].start = {
								x: lines[i].start.x + offsetX,
								y: lines[i].start.y + offsetY,
							};

							lines[i].end = {
								x: lines[i].end.x + offsetX,
								y: lines[i].end.y + offsetY,
							};

							// 如果有控制点也移动
							if (lines[i].type === "arc" && lines[i].controlPoint) {
								lines[i].controlPoint = {
									x: lines[i].controlPoint.x + offsetX,
									y: lines[i].controlPoint.y + offsetY,
								};
							}
						}
					}
				}
				this.modConfirm();
				this.inputNum = null;
			},
			drawAddItem() {
				const that = this;
				if (doors.length) {
					doors.forEach((item) => {
						if (
							item.idx != that.selectData?.idx ||
							that.selectData?.class != item.class
						) {
							that.drawDoor(item, addItemGroupCtx);
							that.drawDoorSizeLine(item, addItemGroupCtx)
						}
						// if (item.isSelected) {
						// 	that.drawControlPoints(item);
						// }
					});

				}
				if (pillarList.length) {
					pillarList.forEach((item) => {
						if (
							item.idx != that.selectData?.idx ||
							that.selectData?.class != item.class
						) {
							that.drawPillar(item, addItemGroupCtx);
							that.drawPillarSizeLine(item, addItemGroupCtx)
						}
						// if (item.isSelected) {
						// 	that.drawControlPoints(item);
						// }
					});
				}
				if (windowList.length) {
					windowList.forEach((item) => {
						if (
							item.idx != that.selectData?.idx ||
							that.selectData?.class != item.class
						) {
							that.drawWindow(item, addItemGroupCtx);
							that.drawWindowSizeLine(item, addItemGroupCtx)
						}
					});
				}
			},
			requestAnimFrame(callback) {
				animationFrameHandle = setTimeout(() => {
					callback();
				}, 1000 / 100); // 固定60帧
				return animationFrameHandle;
			},

			handleSetCrossStart(e) {
				this.isSettingCross = true;
				const touchPos = this.screenToWorld({
					x: e.touches[0].pageX,
					y: e.touches[0].pageY,
				});
				this.previewCross = this.snapToGrid(touchPos.x, touchPos.y);
			},
			handleSetCrossMove(e) {
				if (!this.isSettingCross) return;
				const touchPos = this.screenToWorld({
					x: e.touches[0].pageX,
					y: e.touches[0].pageY,
				});
				this.previewCross = this.snapToGrid(touchPos.x, touchPos.y);
				this.drawDynamicLayer(); // 实时更新预览
			},
			handleSetCrossEnd() {
				if (this.previewCross) {
					this.crosses = [this.previewCross];
					this.crossesIn = true;
				}
				this.isSettingCross = false;
				this.previewCross = null;
				this.updateAllLayers();
			},
			//重置光标
			resetPoint() {
				this.crossesIn = false;
				dynamicCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				dynamicCtx.draw();
			},
			// 背景层（网格，仅渲染一次）
			drawBackground() {
				bgCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				// 计算可见范围（世界坐标）
				const visibleStartX = -this.viewport.offsetX / this.viewport.scale;
				const visibleEndX =
					(wxdata.windowWidth - this.viewport.offsetX) / this.viewport.scale;
				const visibleStartY = -this.viewport.offsetY / this.viewport.scale;
				const visibleEndY =
					(wxdata.windowHeight - this.viewport.offsetY) / this.viewport.scale;
				// 计算网格起始点（世界坐标）
				const startX = Math.floor(visibleStartX / gridSpacing) * gridSpacing;
				const startY = Math.floor(visibleStartY / gridSpacing) * gridSpacing;
				// 网格绘制
				bgCtx.setStrokeStyle("#E0E0E0");
				bgCtx.beginPath();

				// 水平线
				for (
					let wy = Math.floor(visibleStartY / gridSpacing) * gridSpacing; wy <= visibleEndY; wy += gridSpacing
				) {
					const sy = wy * this.viewport.scale + this.viewport.offsetY;
					bgCtx.moveTo(0, sy);
					bgCtx.lineTo(wxdata.windowWidth, sy);
				}

				// 垂直线
				for (
					let wx = Math.floor(visibleStartX / gridSpacing) * gridSpacing; wx <= visibleEndX; wx += gridSpacing
				) {
					const sx = wx * this.viewport.scale + this.viewport.offsetX;
					bgCtx.moveTo(sx, 0);
					bgCtx.lineTo(sx, wxdata.windowHeight);
				}

				bgCtx.stroke();
				bgCtx.draw();
			},
			// 绘制添加物控制点
			drawControlPoints(item) {
				const that = this;
				previewGroupCtx.save();
				// 转换到物体中心点
				const centerPos = that.worldToScreen(item.pos);
				previewGroupCtx.translate(centerPos.x, centerPos.y);

				// 应用旋转（如果有）
				if (item.rotateDeg) {
					previewGroupCtx.rotate((item.rotateDeg * Math.PI) / 180);
				}
				const centerControl = previewGroupCtx.setFillStyle("#FF0000");

				item.dragPoints.forEach((point) => {
					// 转换为相对于物体中心的坐标
					const relativeX = point.x - item.pos.x;
					const relativeY = point.y - item.pos.y;

					// 绘制控制点
					previewGroupCtx.beginPath();
					previewGroupCtx.arc(
						relativeX * that.viewport.scale,
						relativeY * that.viewport.scale,
						6,
						0,
						Math.PI * 2
					);
					previewGroupCtx.fill();

					// 根据类型绘制不同样式的控制点
					if (point.type === "size") {
						previewGroupCtx.setStrokeStyle("#FFFFFF");
						previewGroupCtx.setLineWidth(1);
						previewGroupCtx.stroke();
					}
				});

				previewGroupCtx.restore();
				previewGroupCtx.draw(true);
			},
			// 静态线段层（永久线）
			drawStaticLines() {
				let that = this;
				staticCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				staticCtx.setStrokeStyle(lineColor);
				if (sureRoom.length) {
					for (var i = 0; i < sureRoom.length; i++) {
						const item = sureRoom[i];
						const {
							area
						} = this.calculatePolygonArea(item);
						const center = this.calculatePolygonCenter(item);
						this.drawLinesGroup(item);

						// this.drawSingleLine(data)

						if (center && area > 0) {
							const screenPos = this.worldToScreen(center);

							staticCtx.save();

							// 动态计算文字大小
							const baseSize = 14;
							const fontSize = Math.max(
								baseSize,
								(baseSize * this.viewport.scale) / defaultScale
							);
							staticCtx.setFontSize(fontSize);

							// 测量文字宽度
							const text = `${Math.round(area)} mm²`;
							const textWidth = staticCtx.measureText(text).width;

							// 绘制文字背景（可选）
							staticCtx.setFillStyle("rgba(255, 255, 255, 0.8)");
							staticCtx.fillRect(
								screenPos.x - textWidth / 2 - 5,
								screenPos.y - fontSize / 2 - 2,
								textWidth + 10,
								fontSize + 4
							);

							// 绘制文字
							staticCtx.setFillStyle("#333");
							staticCtx.textAlign = "center";
							staticCtx.textBaseline = "middle";
							staticCtx.fillText(
								"房间" + (i + 1),
								screenPos.x,
								screenPos.y - (1 / 2) * fontSize * 1.2
							);
							staticCtx.fillText(
								text,
								screenPos.x,
								screenPos.y + (1 / 2) * fontSize * 1.2
							);
							staticCtx.restore();
						}
					}
				}

				if (lines.length) {
					this.drawLinesGroup(lines);
				}
				// if (doors.length) {
				//     doors.forEach(door => this.drawDoorSizeLine(door));
				//   }
				//   if (windowList.length) {
				//     windowList.forEach(window => this.drawWindowSizeLine(window));
				//   }
				//   if (pillarList.length) {
				//     pillarList.forEach(pillar => this.drawPillarSizeLine(pillar));
				//   }
				staticCtx.draw(true);
			},
			drawStripedRectangle(x1, y1, x2, y2, lineWidth) {
				staticCtx.save();
				
				    // 转换为屏幕坐标
				    const start = this.worldToScreen({ x: x1, y: y1 });
				    const end = this.worldToScreen({ x: x2, y: y2 });
				
				    // 固定参数
				    const stripeSpacing = 10; // 条纹间隔
				    const stripeAngle = 45;   // 条纹角度（度）
				    const stripeColor = 'black'; // 条纹颜色
				    const bgColor = 'white';  // 背景颜色
				    const borderColor = 'black'; // 边框颜色
				    const borderWidth = 1;    // 边框宽度
				
				    // 计算线段长度和角度
				    const dx = end.x - start.x;
				    const dy = end.y - start.y;
				    const length = Math.sqrt(dx * dx + dy * dy);
				    const angle = Math.atan2(dy, dx);
				
				    // 将坐标系移到起点并旋转
				    staticCtx.translate(start.x, start.y);
				    staticCtx.rotate(angle);
				
				    // 绘制矩形背景
				    staticCtx.fillStyle = bgColor;
				    staticCtx.fillRect(0, -lineWidth / 2, length, lineWidth);
				
				    // 绘制斜条纹
				    staticCtx.strokeStyle = stripeColor;
				    staticCtx.lineWidth = 1;
				
				    const stripeAngleRad = (stripeAngle * Math.PI) / 180;
				    const stripeStep = stripeSpacing / Math.cos(stripeAngleRad);
				
				    // 优化条纹循环范围，仅绘制矩形内的条纹
				    for (let i = 0; i <= length; i += stripeSpacing) {
				        staticCtx.beginPath();
				        const xStart = i;
				        const yStart = -lineWidth / 2;
				        const xEnd = i + lineWidth * Math.tan(stripeAngleRad);
				        const yEnd = lineWidth / 2;
				
				        staticCtx.moveTo(xStart, yStart);
				        staticCtx.lineTo(xEnd, yEnd);
				        staticCtx.stroke();
				    }
				
				    // 绘制边框
				    staticCtx.strokeStyle = borderColor;
				    staticCtx.lineWidth = borderWidth;
				    staticCtx.beginPath();
				    staticCtx.rect(0, -lineWidth / 2, length, lineWidth);
				    staticCtx.stroke();
				
				    staticCtx.restore();
					staticCtx.draw(true)
			},
			drawLinesGroup(linesGroup) {
				staticCtx.save(); // 保存当前绘图状态
			
				for (var i = 0; i < linesGroup.length; i++) {
					
					const l = linesGroup[i];
					const start = this.worldToScreen(l.start);
					const end = this.worldToScreen(l.end);
					if (l.idx == this.focusLine) {
						continue;
					}
					if (l.wallType == 3) {
						this.drawStripedRectangle(l.start.x, l.start.y, l.end.x, l.end.y, l.lineHeight)
						this.drawSizeLine(l);
						continue
					}
					// 设置线段样式
					staticCtx.setStrokeStyle(
						i == this.focusLine ? "red" : l.wallType == 2 ? "#000" : "#cdf"
					);
					staticCtx.setLineWidth(l.lineHeight);
					if (i != linesGroup.length - 1) {
						staticCtx.setLineCap("square");
					} else {
						staticCtx.setLineCap("butt");
					}



					staticCtx.beginPath();
					staticCtx.moveTo(start.x, start.y);

					if (l.type === "arc" && l.controlPoint) {
						// 绘制弧线
						const cp = this.worldToScreen(l.controlPoint);
						staticCtx.quadraticCurveTo(cp.x, cp.y, end.x, end.y);
						staticCtx.stroke();
						// 如果是选中线段，绘制控制点
						// if (i == this.focusLine) {
						//   staticCtx.beginPath();
						//   staticCtx.setLineWidth(1);
						//   staticCtx.arc(cp.x, cp.y, 10, 0, Math.PI * 2, false);
						//   staticCtx.stroke();
						// }
					} else {
						// 绘制直线
						staticCtx.lineTo(end.x, end.y);
					}

					staticCtx.stroke();

					// 绘制尺寸标注
					this.drawSizeLine(l);
				}

				staticCtx.restore(); // 恢复绘图状态
				staticCtx.draw(true);
			},
			// 绘制标尺线
			drawSizeLine(l) {
				staticCtx.save();
				const start = this.worldToScreen(l.start);
				const end = this.worldToScreen(l.end);
				const midWorld = {
					x: (l.start.x + l.end.x) / 2,
					y: (l.start.y + l.end.y) / 2,
				};

				// 计算线段向量和长度
				const deltaX = end.x - start.x;
				const deltaY = end.y - start.y;
				const length = Math.sqrt(deltaX ** 2 + deltaY ** 2);
				const angle = Math.atan2(deltaY, deltaX);

				// 计算垂直偏移方向（确保标注在外侧）
				const perpendicular = {
					x: -deltaY,
					y: deltaX,
				};
				const normalize = (vec) => {
					const len = Math.sqrt(vec.x ** 2 + vec.y ** 2);
					return {
						x: vec.x / len,
						y: vec.y / len,
					};
				};
				const normal = normalize(perpendicular);

				// 动态偏移量（标注线与墙体的距离）
				const lineOffset = Math.max(30, defaultScale * 0.8); // 标注线偏移量
				const textOffset = lineOffset + 15; // 文字在标注线基础上再偏移15像素

				// 标注文字内容（实际长度，单位毫米）
				const worldLength = Math.round(distance(l.start, l.end));
				l.lineWidth = worldLength;
				const labelText = `${worldLength}`;

				// 1. 绘制外侧平行标注线（与墙体平行且等长）
				staticCtx.setStrokeStyle("red");
				staticCtx.setLineWidth(1);
				staticCtx.beginPath();
				const lineStart = {
					x: midWorld.x * this.viewport.scale +
						this.viewport.offsetX +
						normal.x * lineOffset -
						(length / 2) * Math.cos(angle),
					y: midWorld.y * this.viewport.scale +
						this.viewport.offsetY +
						normal.y * lineOffset -
						(length / 2) * Math.sin(angle),
				};
				const lineEnd = {
					x: midWorld.x * this.viewport.scale +
						this.viewport.offsetX +
						normal.x * lineOffset +
						(length / 2) * Math.cos(angle),
					y: midWorld.y * this.viewport.scale +
						this.viewport.offsetY +
						normal.y * lineOffset +
						(length / 2) * Math.sin(angle),
				};
				staticCtx.moveTo(lineStart.x, lineStart.y);
				staticCtx.lineTo(lineEnd.x, lineEnd.y);
				staticCtx.stroke();

				// 2. 计算文字位置（在标注线的基础上再偏移一定距离）
				const textPos = {
					x: midWorld.x * this.viewport.scale +
						this.viewport.offsetX +
						normal.x * textOffset,
					y: midWorld.y * this.viewport.scale +
						this.viewport.offsetY +
						normal.y * textOffset,
				};

				// 4. 绘制文字
				staticCtx.setFontSize(12);
				staticCtx.setFillStyle("red");
				staticCtx.textAlign = "center";
				staticCtx.textBaseline = "middle";
				staticCtx.fillText(labelText, textPos.x, textPos.y);

				staticCtx.restore();
			},
			// 贝塞尔曲线长度近似计算
			approximateBezierLength(p0, p1, p2, steps = 20) {
				let length = 0;
				let prev = p0;

				for (let i = 1; i <= steps; i++) {
					const t = i / steps;
					const current = {
						x: (1 - t) * (1 - t) * p0.x + 2 * (1 - t) * t * p1.x + t * t * p2.x,
						y: (1 - t) * (1 - t) * p0.y + 2 * (1 - t) * t * p1.y + t * t * p2.y,
					};
					length += distance(prev, current);
					prev = current;
				}

				return Math.round(length);
			},
			// 添加绘制的线
			drawSingleLine(line) {
				this.drawWall(line, lines, lines.length - 1);
				this.drawSizeLine(line);
				staticCtx.draw(true);
			},
			// 绘制墙体
			drawWall(line, lineGroup, idx) {
				const start = this.worldToScreen(line.start);
				const end = this.worldToScreen(line.end);

				if (line.wallType == 1 || !line.wallType || line.wallType == 2) {
					staticCtx.setStrokeStyle(
						idx == this.focusLine ? "red" : line.wallType == 2 ? "#000" : "#cdf"
					);

					staticCtx.setLineWidth(line.lineHeight);

					// 确保线段端点绘制完整
					// staticCtx.setLineCap('square');

					staticCtx.beginPath();
					staticCtx.moveTo(start.x, start.y);

					// staticCtx.lineTo(end.x, end.y);
					if (line.type === "arc" && line.controlPoint) {
						// 使用二次贝塞尔曲线绘制弧线
						const cp = this.worldToScreen(line.controlPoint);
						staticCtx.quadraticCurveTo(cp.x, cp.y, end.x, end.y);
						staticCtx.stroke();
						if (idx == this.focusLine) {
							staticCtx.beginPath();
							staticCtx.setLineWidth(1);
							staticCtx.arc(cp.x, cp.y, 10, 0, Math.PI * 2, false);
						}
					} else {
						// 普通直线
						staticCtx.lineTo(end.x, end.y);
					}
					staticCtx.stroke();

					// 重置线帽样式
					staticCtx.setLineCap("butt");
				}
			},
			// 点击闭合
			closePic() {
				this.selectData = null;
				const addLine = this.waitCloseLine.map((item, idx) => {
					return {
						start: item.start,
						end: item.end,
						idx: lines.length + idx,
						lineHeight: 10,
					};
				});
				lines = [...lines, ...addLine];
				console.log(lines);
				this.closeFine();
			},
			// 线段闭合完成
			closeFine() {
				this.crossesIn = false;
				this.waitCloseLine = null;
				lines = lines.map((item) => {
					item.roomId = sureRoom.length;
					return item;
				});
				sureRoom = [...sureRoom, lines];
				lines = [];
				this.updateAllLayers();
			},
			// 检测点位距离最近的线段
			isPointNearLine(point, line, threshold) {
				const {
					start,
					end,
					type,
					controlPoint
				} = line;

				if (type === "arc" && controlPoint) {
					// 使用二次贝塞尔曲线近似检测

					return this.isPointNearBezier(
						point,
						start,
						controlPoint,
						end,
						threshold
					);
				} else {
					const a = {
						x: start.x,
						y: start.y,
					};
					const b = {
						x: end.x,
						y: end.y,
					};
					// 线段长度
					const lineLength = distance(a, b);
					if (lineLength === 0) return distance(point, a) <= threshold;
					// 投影计算
					const t = Math.max(
						0,
						Math.min(
							1,
							((point.x - a.x) * (b.x - a.x) + (point.y - a.y) * (b.y - a.y)) /
							lineLength ** 2
						)
					);
					// 最近投影点
					const projection = {
						x: a.x + t * (b.x - a.x),
						y: a.y + t * (b.y - a.y),
					};
					// 计算实际距离
					return distance(point, projection) <= threshold;
				}
			},
			// 动态层（十字标+预览线）
			drawDynamicLayer() {
				let that = this;
				if (this.isSettingCross && this.previewCross) {
					const pos = this.worldToScreen(this.previewCross);
					const crossSize = 15;
					dynamicCtx.setStrokeStyle(activeCross ? "#00FF00" : "#000"); // 使用绿色作为预览颜色
					dynamicCtx.beginPath();
					dynamicCtx.moveTo(pos.x - crossSize, pos.y);
					dynamicCtx.lineTo(pos.x + crossSize, pos.y);
					dynamicCtx.moveTo(pos.x, pos.y - crossSize);
					dynamicCtx.lineTo(pos.x, pos.y + crossSize);
					dynamicCtx.stroke();
				}

				// 十字光标绘制（在drawDynamicLayer中）
				if (this.crossesIn) {
					const crossSize = 10; // 随缩放比例变化
					that.crosses.forEach((origin) => {
						const pos = that.worldToScreen(origin);
						dynamicCtx.beginPath(); // 必须添加

						dynamicCtx.moveTo(pos.x - crossSize, pos.y);
						dynamicCtx.lineTo(pos.x + crossSize, pos.y);
						dynamicCtx.moveTo(pos.x, pos.y - crossSize);
						dynamicCtx.lineTo(pos.x, pos.y + crossSize);
						dynamicCtx.stroke(); // 必须添加
					});
				}
				// 绘制橙色预览线（动态更新）
				if (activeCross && originPos) {
					const oriPos = that.worldToScreen(originPos);
					const actPos = that.worldToScreen(activeCross);
					dynamicCtx.setStrokeStyle(previewColor);
					dynamicCtx.beginPath();
					dynamicCtx.moveTo(oriPos.x, oriPos.y);
					dynamicCtx.lineTo(actPos.x, actPos.y);
					dynamicCtx.stroke();
				}
				if (
					lines.length > 1 &&
					lines[lines.length - 1].end.x != lines[0].start.x &&
					lines[lines.length - 1].end.y != lines[0].start.y
				) {
					const point = this.JudgmentPoint();
					dynamicCtx.beginPath();
					dynamicCtx.setLineDash([5, 5]);
					this.waitCloseLine = [{
							start: {
								x: lines[lines.length - 1].end.x,
								y: lines[lines.length - 1].end.y,
							},
							end: {
								x: point.x,
								y: point.y,
							},
						},
						{
							start: {
								x: point.x,
								y: point.y,
							},
							end: {
								x: lines[0].start.x,
								y: lines[0].start.y,
							},
						},
					];
					dynamicCtx.moveTo(
						that.worldToScreen(lines[lines.length - 1].end).x,
						that.worldToScreen(lines[lines.length - 1].end).y
					);
					dynamicCtx.lineTo(
						that.worldToScreen(point).x,
						that.worldToScreen(point).y
					);
					dynamicCtx.stroke();
					dynamicCtx.moveTo(
						that.worldToScreen(point).x,
						that.worldToScreen(point).y
					);
					dynamicCtx.lineTo(
						that.worldToScreen(lines[0].start).x,
						that.worldToScreen(lines[0].start).y
					);
					dynamicCtx.stroke();
					dynamicCtx.setLineDash([]);
				}
				dynamicCtx.draw();
			},

			// 触摸处理（优化性能）
			handleTouchStart(e) {
				e.preventDefault();
				const that = this;
				const touchX = e.touches[0].x;
				const touchY = e.touches[0].y;

				// 转换到世界坐标
				const worldPos = that.screenToWorld({
					x: touchX,
					y: touchY,
				});

				const pos = that.snapToGrid(worldPos.x, worldPos.y);
				// 检查是否点击了拖动元素
				const threshold = 10 / that.viewport.scale;

				// 1. 首先检查是否点击了控制点
				const clickedControlPoint = that.findClickedControlPoint(
					worldPos,
					threshold
				); // 使用更小的阈值

				if (clickedControlPoint) {
					that.selectData = clickedControlPoint.item;
					that.selectData.activeControlPoint = clickedControlPoint.point;
					return;
				} else {
					that.selecctData = null;
				}
				that.isDragging = true;
				// 查找最近十字标（扩大感应区域）
				activeCross = that.crosses.find(
					(c) =>
					Math.abs(c.x - pos.x) < gridSpacing * 1.2 &&
					Math.abs(c.y - pos.y) < gridSpacing * 1.2
				);
				if (activeCross) {
					originPos = {
						x: activeCross.x,
						y: activeCross.y,
					};
				}
				that.dragStart = {
					x: touchX,
					y: touchY,
				};
			},
			handleTouchMove(e) {
				e.preventDefault();
				const that = this;
				if (e.touches.length === 2) {
					// 双指缩放
					const p1 = e.touches[0];
					const p2 = e.touches[1];
					const currentDistance = Math.sqrt(
						Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)
					);

					if (!initialDistance) {
						initialDistance = currentDistance;
						// 记录缩放中心点
						scaleCenter = {
							x: (p1.x + p2.x) / 2,
							y: (p1.y + p2.y) / 2,
						};
						return;
					}

					const scale = currentDistance / initialDistance;
					const newScale = Math.max(
						20,
						Math.min(60, this.viewport.scale * scale)
					);

					// 计算缩放中心的世界坐标
					const worldCenter = this.screenToWorld(scaleCenter);

					// 调整偏移量以保持中心点不变
					this.viewport.offsetX = scaleCenter.x - worldCenter.x * newScale;
					this.viewport.offsetY = scaleCenter.y - worldCenter.y * newScale;
					this.viewport.scale = newScale;

					initialDistance = currentDistance;

					// 节流更新
					if (!scaleRafPending) {
						scaleRafPending = true;
						this.requestAnimFrame(() => {
							that.updateAllLayers();
							scaleRafPending = false;
						});
					}
				} else {
					const touchPos = this.screenToWorld({
						x: e.touches[0].x,
						y: e.touches[0].y,
					});
					if (
						this.selectData &&
						this.selectData.controlPoint &&
						distance(touchPos, this.selectData.controlPoint) <
						40 / this.viewport.scale
					) {
						that.changeArcPos(this.selectData, touchPos);
						return;
					}
					if (that.selectData?.activeControlPoint) {
						// 拖动控制点
						const newPos = that.snapToGrid(touchPos.x, touchPos.y);
						if (
							that.selectData.class == "door" ||
							that.selectData.class == "window"
						) {
							that.selectData.activeControlPoint.y =
								that.selectData.activeControlPoint.y || newPos.y;
							that.selectData.activeControlPoint.x = newPos.x;
						} else if (that.selectData.class == "pillar") {
							if (
								that.selectData.activeControlPoint.direct == 1 ||
								that.selectData.activeControlPoint.direct == 2
							) {
								that.selectData.activeControlPoint.y =
									that.selectData.activeControlPoint.y || newPos.y;
								that.selectData.activeControlPoint.x = newPos.x;
							} else {
								that.selectData.activeControlPoint.y = newPos.y;
								that.selectData.activeControlPoint.x =
									that.selectData.activeControlPoint.x || newPos.x;
							}
						}

						// 根据控制点更新元素属性
						if (!rafPending) {
							rafPending = true;
							that.requestAnimFrame(() => {
								that.updateItemByControlPoints(that.selectData);
								rafPending = false;
							});
						}
						return;

						// drawDynamicLayer();
					} else if (that.selectData?.class) {
						that.selectData.pos = that.snapToGrid(touchPos.x, touchPos.y);
						if (that.selectData.class == "door") {
							// that.selectData = doors[that.selectData.idx];
							if (that.selectData.type == 1) {
								that.selectData.dragPoints[0] = {
									...that.selectData.dragPoints[0],
									...that.snapToGrid(touchPos.x, touchPos.y),
								};
								that.selectData.dragPoints[1] = {
									...that.selectData.dragPoints[1],
									...that.snapToGrid(
										touchPos.x + that.selectData.width / that.viewport.scale,
										touchPos.y
									),
								};
							} else if (that.selectData.type == 2) {
								that.selectData.dragPoints[0] = {
									...that.selectData.dragPoints[0],
									...that.snapToGrid(
										touchPos.x - that.selectData.width / 2 / that.viewport.scale,
										touchPos.y
									),
								};
								that.selectData.dragPoints[1] = {
									...that.selectData.dragPoints[1],
									...that.snapToGrid(
										touchPos.x + that.selectData.width / 2 / that.viewport.scale,
										touchPos.y
									),
								};
							}

							// that.updateAllLayers()
						} else if (that.selectData?.class == "window") {
							// data = windowList[that.selectData.idx];
							// data.pos = that.snapToGrid(touchPos.x, touchPos.y);
							that.selectData.dragPoints[0] = {
								...that.selectData.dragPoints[0],
								...that.snapToGrid(
									touchPos.x -
									((1 / 2) * that.selectData.width) / that.viewport.scale,
									touchPos.y
								),
							};
							that.selectData.dragPoints[1] = {
								...that.selectData.dragPoints[1],
								...that.snapToGrid(
									touchPos.x +
									((1 / 2) * that.selectData.width) / that.viewport.scale,
									touchPos.y
								),
							};
							// 根据控制点更新元素属性
						} else if (that.selectData?.class == "pillar") {
							if (this.selectData.type == 1) {
								that.selectData.dragPoints[0] = {
									...that.selectData.dragPoints[0],
									...that.snapToGrid(
										touchPos.x -
										((1 / 2) * that.selectData.width) / that.viewport.scale,
										touchPos.y
									),
								};
								that.selectData.dragPoints[1] = {
									...that.selectData.dragPoints[1],
									...that.snapToGrid(
										touchPos.x +
										((1 / 2) * that.selectData.width) / that.viewport.scale,
										touchPos.y
									),
								};
								that.selectData.dragPoints[2] = {
									...that.selectData.dragPoints[2],
									...that.snapToGrid(
										touchPos.x,
										touchPos.y +
										((1 / 2) * that.selectData.height) / that.viewport.scale
									),
								};
								that.selectData.dragPoints[3] = {
									...that.selectData.dragPoints[3],
									...that.snapToGrid(
										touchPos.x,
										touchPos.y -
										((1 / 2) * that.selectData.height) / that.viewport.scale
									),
								};

								// 根据控制点更新元素属性
								// that.updateAllLayers()
							} else if (this.selectData.type == 2) {
								that.selectData.dragPoints[0] = {
									...that.selectData.dragPoints[0],
									...that.snapToGrid(
										touchPos.x -
										((1 / 2) * that.selectData.width) / that.viewport.scale,
										touchPos.y
									),
								};
								that.selectData.dragPoints[1] = {
									...that.selectData.dragPoints[1],
									...that.snapToGrid(
										touchPos.x +
										((1 / 2) * that.selectData.width) / that.viewport.scale,
										touchPos.y
									),
								};
								that.selectData.dragPoints[2] = {
									...that.selectData.dragPoints[2],
									...that.snapToGrid(
										touchPos.x,
										touchPos.y +
										((1 / 2) * that.selectData.width) / that.viewport.scale
									),
								};
								that.selectData.dragPoints[3] = {
									...that.selectData.dragPoints[3],
									...that.snapToGrid(
										touchPos.x,
										touchPos.y -
										((1 / 2) * that.selectData.width) / that.viewport.scale
									),
								};
							}
						}

						if (!rafPending) {
							rafPending = true;
							that.requestAnimFrame(() => {
								previewGroupCtx.clearRect(
									0,
									0,
									wxdata.windowWidth,
									wxdata.windowHeight
								);
								previewGroupCtx.draw(true);

								if (that.selectData.class === "door") {
									that.drawDoor(that.selectData, previewGroupCtx);
									// item.dragPoints = this.createDoorControlPoints(item);
								} else if (that.selectData.class === "window") {
									that.drawWindow(that.selectData, previewGroupCtx);
									// item.dragPoints = this.createWindowControlPoints(item);
								} else if (that.selectData.class === "pillar") {
									that.drawPillar(that.selectData, previewGroupCtx);
									// item.dragPoints = this.createPillarControlPoints(item);
								}
								// that.drawAddItem();
								that.drawControlPoints(this.selectData);
								rafPending = false;
							});
						}

						return;
					} else if (activeCross) {
						// 处理十字标移动

						const newPos = that.snapToGrid(touchPos.x, touchPos.y);

						// 直接修改响应式数据
						activeCross.x = newPos.x;
						activeCross.y = newPos.y;
						that.drawDynamicLayer();
						return;
					} else if (that.isDragging) {
						// 单指拖动
						const deltaX = e.touches[0].x - this.dragStart.x;
						const deltaY = e.touches[0].y - this.dragStart.y;
						this.viewport.offsetX += deltaX;
						this.viewport.offsetY += deltaY;
						this.dragStart = {
							x: e.touches[0].x,
							y: e.touches[0].y,
						};

						// 节流更新
						if (!dragRafPending) {
							dragRafPending = true;
							previewGroupCtx.clearRect(
								0,
								0,
								wxdata.windowWidth,
								wxdata.windowHeight
							);
							previewGroupCtx.draw(true);
							this.requestAnimFrame(() => {
								that.updateAllLayers();
								dragRafPending = false;
							});
						}
						// 替换原有的图层更新调用
					}
				}
			},

			handleTouchEnd(e) {
				e.preventDefault();
				initialDistance = null;
				scaleCenter = null;

				if (this.selectData && this.selectData.activeControlPoint) {
					this.selectData.activeControlPoint = null;
				}

				if (activeCross) {
					const prevLine = lines.length > 0 ? lines[lines.length - 1] : null;
					const adjustedStartPos = this.adjustLineStart(prevLine, originPos);

					const newLine = {
						start: adjustedStartPos,
						end: {
							...activeCross,
						},
						idx: lines.length,
						lineHeight: 10,
						controlPoint: {
							x: activeCross.x - adjustedStartPos.x,
							y: activeCross.y - adjustedStartPos.y,
						},
						type: "line",
					};

					lines.push(newLine);
					this.drawStaticLines();

					if (
						activeCross.x == lines[0].start.x &&
						activeCross.y == lines[0].start.y &&
						lines.length > 2
					) {
						this.closeFine();
					}
					activeCross = null;
					originPos = null;
					this.drawDynamicLayer();
				}
			},
			// 修改线段检测逻辑（使用世界坐标）
			handleTap(event) {
				const screenX = event.detail.x;
				const screenY = event.detail.y;
				this.focusLine = null;
				this.modMainData = null;

				const worldPos = this.screenToWorld({
					x: screenX,
					y: screenY,
				});
				// 动态计算阈值（考虑缩放因素）
				const threshold = 10 / this.viewport.scale;
				// 2. 检查是否点击了已有物体

				// this.selectData = null;
				this.addItemsShow = false;

				// 查找被点击的线段
				let clickedLine = lines.find((line) =>
					this.isPointNearLine(worldPos, line, threshold)
				);
				// const clickedLineIdx = lines.findIndex((line) =>
				//   this.isPointNearLine(worldPos, line, threshold)
				// );
				if (clickedLine) {
					this.focusLine = clickedLine.idx;
					this.selectData = clickedLine;
					this.drawSymbol(this.selectData);
					this.drawStaticLines();
				} else if (this.findClickedItem(worldPos, threshold)) {
					const clickitem = this.findClickedItem(worldPos, threshold);
					if (
						clickitem.idx == this.selectData?.idx &&
						clickitem.class == this.selectData?.class
					) {
						return;
					}

					this.selectData = this.findClickedItem(worldPos, threshold);
					previewGroupCtx.clearRect(
						0,
						0,
						wxdata.windowWidth,
						wxdata.windowHeight
					);
					previewGroupCtx.draw(true);
					addItemGroupCtx.clearRect(
						0,
						0,
						wxdata.windowWidth,
						wxdata.windowHeight
					);
					addItemGroupCtx.draw(true);

					if (this.selectData.class === "door") {
						this.drawDoor(this.selectData, previewGroupCtx);
						// item.dragPoints = this.createDoorControlPoints(item);
					} else if (this.selectData.class === "window") {
						this.drawWindow(this.selectData, previewGroupCtx);
						// item.dragPoints = this.createWindowControlPoints(item);
					} else if (this.selectData.class === "pillar") {
						this.drawPillar(this.selectData, previewGroupCtx);
						// item.dragPoints = this.createPillarControlPoints(item);
					}
					this.drawControlPoints(this.selectData);

					this.drawAddItem();
					// return;
				} else {
					if (this.selectData) {
						previewGroupCtx.clearRect(
							0,
							0,
							wxdata.windowWidth,
							wxdata.windowHeight
						);
						previewGroupCtx.draw(true);
						if (
							this.selectData?.type == "line" ||
							this.selectData?.type == "arc" ||
							!this.selectData.type
						) {
							lines[this.selectData.idx] = this.selectData;
							this.drawStaticLines();
							this.focusLine = null;
							this.selectData = null;
						} else if (this.selectData.class) {
							if (this.selectData.class == "door") {
								doors[this.selectData.idx] = this.selectData;
							} else if (this.selectData.class == "window") {
								windowList[this.selectData.idx] = this.selectData;
							} else if (this.selectData.class == "pillar") {
								pillarList[this.selectData.idx] = this.selectData;
							}
							// this.clearSelection();
							this.selectData = null;
							this.drawAddItem();
						}
					}
				}
				// addItemGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				// this.drawAddItem();
			},
			drawSymbol(obj) {
				previewGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);

				if (obj.type == "line" || obj.type == "arc" || !obj.type) {
					// 设置线段样式
					previewGroupCtx.setStrokeStyle("red");
					previewGroupCtx.setLineWidth(obj.lineHeight);
					previewGroupCtx.setLineCap("square");

					const start = this.worldToScreen(obj.start);
					const end = this.worldToScreen(obj.end);

					previewGroupCtx.beginPath();
					previewGroupCtx.moveTo(start.x, start.y);

					if (obj.type === "arc" && obj.controlPoint) {
						// 绘制弧线
						const cp = this.worldToScreen(obj.controlPoint);
						previewGroupCtx.quadraticCurveTo(cp.x, cp.y, end.x, end.y);

						// }
					} else {
						// 绘制直线
						previewGroupCtx.lineTo(end.x, end.y);
					}

					previewGroupCtx.stroke();
					if (obj.type == "arc" && obj.controlPoint) {
						const cp = this.worldToScreen(obj.controlPoint);
						previewGroupCtx.beginPath();
						previewGroupCtx.setLineWidth(1);
						previewGroupCtx.arc(cp.x, cp.y, 10, 0, Math.PI * 2);
						previewGroupCtx.stroke();
					}
					previewGroupCtx.draw(true);
					// 绘制尺寸标注
					// this.drawSizeLine(obj);
				}
			},
			changeArcPos(data, newPos) {
				data.controlPoint = newPos;

				this.drawSymbol(data);
			},
			//根据控制点位更新地图
			updateItemByControlPoints(item) {
				// previewGroupCtx.clearRect(0,0,wxdata.windowWidth,wxdata.windowHeight)
				previewGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				this.drawControlPoints(item);
				if (item.class === "door") {
					// 根据控制点更新门的位置/大小
					const sizePoint = item.activeControlPoint;
					if (sizePoint) {
						if (item.type == 1) {
							item.width = distance(item.pos, sizePoint) * this.viewport.scale;
						} else if (item.type == 2) {
							item.width =
								distance(item.pos, sizePoint) * this.viewport.scale +
								item.width / 2;

							item.dragPoints[0].x = item.pos.x - distance(item.pos, sizePoint);
						}
					}
					this.drawDoor(item, previewGroupCtx);
				} else if (item.class === "window") {
					// 更新窗户大小
					const sizePoint = item.activeControlPoint;
					if (sizePoint) {
						const disWidth = (sizePoint.x - item.pos.x) * this.viewport.scale;
						const defaultWidth = item.width;
						item.width = disWidth + (1 / 2) * defaultWidth;
						item.dragPoints[0].x =
							item.pos.x - item.width / this.viewport.scale / 2;
						item.dragPoints[0].y = item.pos.y;
						item.dragPoints[1].x =
							item.pos.x + item.width / this.viewport.scale / 2;
						item.dragPoints[1].y = item.pos.y;
					}
					this.drawWindow(item, previewGroupCtx);
				} else if (item.class == "pillar") {
					const sizePoint = item.activeControlPoint;
					if (sizePoint) {
						if (item.type == 1) {
							if (
								item.activeControlPoint.direct == 1 ||
								item.activeControlPoint.direct == 2
							) {
								const disWidth = (sizePoint.x - item.pos.x) * this.viewport.scale;
								const defaultWidth = item.width;
								item.width = disWidth + (1 / 2) * defaultWidth;
								item.dragPoints[0].x =
									item.pos.x - item.width / this.viewport.scale / 2;
								item.dragPoints[0].y = item.pos.y;
								item.dragPoints[1].x =
									item.pos.x + item.width / this.viewport.scale / 2;
								item.dragPoints[1].y = item.pos.y;
							} else {
								const disHeight =
									(sizePoint.y - item.pos.y) * this.viewport.scale;

								const defaultHeight = item.height;
								item.height = disHeight + (1 / 2) * defaultHeight;
								item.dragPoints[2].y =
									item.pos.y - item.height / this.viewport.scale / 2;
								item.dragPoints[2].x = item.pos.x;
								item.dragPoints[3].y =
									item.pos.y + item.height / this.viewport.scale / 2;
								item.dragPoints[3].x = item.pos.x;
							}
						} else if (item.type == 2) {
							let disWidth;
							if (
								item.activeControlPoint.direct == 1 ||
								item.activeControlPoint.direct == 2
							) {
								disWidth = Math.abs(
									(sizePoint.x - item.pos.x) * this.viewport.scale
								);
							} else {
								disWidth = Math.abs(
									(sizePoint.y - item.pos.y) * this.viewport.scale
								);
							}
							const defaultWidth = item.width;
							item.width = disWidth + (1 / 2) * defaultWidth;
							item.dragPoints[0].x =
								item.pos.x - item.width / this.viewport.scale / 2;
							item.dragPoints[0].y = item.pos.y;
							item.dragPoints[1].x =
								item.pos.x + item.width / this.viewport.scale / 2;
							item.dragPoints[1].y = item.pos.y;
							item.dragPoints[2].y =
								item.pos.y - item.width / this.viewport.scale / 2;
							item.dragPoints[2].x = item.pos.x;
							item.dragPoints[3].y =
								item.pos.y + item.width / this.viewport.scale / 2;
							item.dragPoints[3].x = item.pos.x;
						} else if (item.type === "arc") {
							// 更新弧线控制点
							const controlPoint = item.activeControlPoint;
							if (controlPoint) {
								item.controlPoint = {
									x: controlPoint.x,
									y: controlPoint.y,
								};
							}
						}
					}
					this.drawPillar(item, previewGroupCtx);
				}
				// this.drawAddItem();
			},
			// 新增屏幕坐标边界检查
			clampViewport() {
				const maxOffsetX = wxdata.windowWidth * 0.8;
				const maxOffsetY = wxdata.windowHeight * 0.8;
				this.viewport.offsetX = Math.max(
					-maxOffsetX,
					Math.min(maxOffsetX, this.viewport.offsetX)
				);
				this.viewport.offsetY = Math.max(
					-maxOffsetY,
					Math.min(maxOffsetY, this.viewport.offsetY)
				);
			},
			// 在视口变化时更新静态层
			updateAllLayers() {
				const that = this;
				this.clampViewport();
				const clearPromises = [
					new Promise((resolve) => {
						bgCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
						resolve();
					}),
					new Promise((resolve) => {
						staticCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
						resolve();
					}),
					new Promise((resolve) => {
						addItemGroupCtx.clearRect(
							0,
							0,
							wxdata.windowWidth,
							wxdata.windowHeight
						);
						resolve();
					}),
					new Promise((resolve) => {
						previewGroupCtx.clearRect(
							0,
							0,
							wxdata.windowWidth,
							wxdata.windowHeight
						);
						resolve();
					}),
					new Promise((resolve) => {
						dynamicCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
						resolve();
					}),
				];
				// 2. 按顺序重绘所有图层
				Promise.all(clearPromises).then(() => {
					// 先绘制背景和静态内容
					that.drawBackground();
					that.drawStaticLines();

					// 然后绘制动态内容
					that.drawDynamicLayer();

					// 最后绘制添加的物件和控制点
					that.drawAddItem();
					if (
						this.selectData &&
						(this.selectData.type == "line" || this.selectData.type == "arc")
					) {
						this.drawSymbol(this.selectData);
					}
				});
			},
			worldToScreen(point) {
				return {
					x: point.x * this.viewport.scale + this.viewport.offsetX,
					y: point.y * this.viewport.scale + this.viewport.offsetY,
				};
			},

			screenToWorld(point) {
				return {
					x: (point.x - this.viewport.offsetX) / this.viewport.scale,
					y: (point.y - this.viewport.offsetY) / this.viewport.scale,
				};
			},

			// 计算线段夹角
			adjustLineStart(prevLine, currentStart) {
				if (!prevLine) return currentStart;

				// 计算上一个线段的方向
				const dx = prevLine.end.x - prevLine.start.x;
				const dy = prevLine.end.y - prevLine.start.y;
				const length = Math.sqrt(dx * dx + dy * dy);

				if (length === 0) return currentStart;

				// 计算当前点到上一个线段的投影
				const t =
					((currentStart.x - prevLine.start.x) * dx +
						(currentStart.y - prevLine.start.y) * dy) /
					(length * length);

				// 如果投影点在线段上，使用投影点作为新的起点
				if (t >= 0 && t <= 1) {
					return {
						x: prevLine.start.x + t * dx,
						y: prevLine.start.y + t * dy,
					};
				}

				return currentStart;
			},
			JudgmentPoint() {
				const lastPoint = lines[lines.length - 1].end;
				const firstPoint = lines[0].start;
				const directPoint = {};
				//判断最后一个点距离初始点的位置信息
				if (Math.abs(lastPoint.x) > Math.abs(firstPoint.x)) {
					directPoint.y = lastPoint.y;
				} else {
					directPoint.y = firstPoint.y;
					// directPoint.y = firstPoint.y;
				}
				if (Math.abs(lastPoint.y) > Math.abs(firstPoint.y)) {
					directPoint.x = firstPoint.x;
				} else {
					directPoint.x = lastPoint.x;
				}
				return directPoint;
			},
			// 网格吸附（精确对齐）
			snapToGrid(x, y) {
				return {
					x: Math.round(x / gridSpacing) * gridSpacing,
					y: Math.round(y / gridSpacing) * gridSpacing,
				};
			},

			clearSelection() {
				// 清除所有元素的选中状态和控制点
				[...doors, ...windowList, ...pillarList].forEach((item) => {
					item.isSelected = false;
					// item.dragPoints = [];
				});
				if (this.selectData) {
					this.selectData.activeControlPoint = null;
				}
				this.selectData = null;
				this.updateAllLayers();
			},

			findClickedControlPoint(point, threshold) {
				threshold = threshold || 5 / this.viewport.scale;
				// 检查所有可选中元素的控制点
				const allItems = [...doors, ...windowList, ...pillarList];
				for (const item of allItems) {
					if (!item.dragPoints) continue;

					for (const controlPoint of item.dragPoints) {
						if (distance(point, controlPoint) < threshold) {
							return {
								item,
								point: controlPoint,
							};
						}
					}
				}
				return null;
			},

			findClickedItem(point, threshold) {
				threshold = threshold || 10 / this.viewport.scale;
				for (let i = pillarList.length - 1; i >= 0; i--) {
					if (this.isPointNearPillar(point, pillarList[i], threshold))
						return pillarList[i];
				}

				for (let i = windowList.length - 1; i >= 0; i--) {
					if (this.isPointNearWindow(point, windowList[i], threshold))
						return windowList[i];
				}

				for (let i = doors.length - 1; i >= 0; i--) {
					if (this.isPointNearDoor(point, doors[i], threshold)) return doors[i];
				}

				return null;
			},

			isPointNearDoor(point, door, threshold) {
				const doorRect = {
					x: door.pos.x - door.width / 2 / this.viewport.scale, // 转换为世界坐标
					y: door.pos.y - door.width / 2 / this.viewport.scale, // 门通常是正方形
					width: door.width / this.viewport.scale,
					height: door.width / this.viewport.scale,
				};
				return this.isPointInRect(point, doorRect, threshold);
			},

			isPointNearWindow(point, window, threshold) {
				const windowRect = {
					x: window.pos.x - window.width / 2 / this.viewport.scale,
					y: window.pos.y - (window.height || 10) / 2 / this.viewport.scale,
					width: window.width / this.viewport.scale,
					height: (window.height || 10) / this.viewport.scale,
				};
				return this.isPointInRect(point, windowRect, threshold);
			},

			isPointNearPillar(point, pillar, threshold) {
				if (pillar.type === 2) {
					// 圆形柱子
					return (
						distance(point, pillar.pos) <
						pillar.width / 2 / this.viewport.scale + threshold
					);
				} else {
					// 方形柱子
					const pillarRect = {
						x: pillar.pos.x - pillar.width / 2 / this.viewport.scale,
						y: pillar.pos.y -
							(pillar.height || pillar.width) / 2 / this.viewport.scale,
						width: pillar.width / this.viewport.scale,
						height: (pillar.height || pillar.width) / this.viewport.scale,
					};
					return this.isPointInRect(point, pillarRect, threshold);
				}
			},

			isPointInRect(point, rect, threshold) {
				return (
					point.x >= rect.x - threshold &&
					point.x <= rect.x + rect.width + threshold &&
					point.y >= rect.y - threshold &&
					point.y <= rect.y + rect.height + threshold
				);
			},

			selectItem(item) {
				// item.isSelected = true;
				addItemGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				addItemGroupCtx.draw(true);
				this.drawAddItem();
				this.selectData = item;
				previewGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				// 根据元素类型设置控制点

				if (item.type === "door") {
					this.drawDoor(this.selectData, previewGroupCtx);
					// item.dragPoints = this.createDoorControlPoints(item);
				} else if (item.type === "window") {
					this.drawWindow(this.selectData, previewGroupCtx);
					// item.dragPoints = this.createWindowControlPoints(item);
				} else if (item.type === "pillar") {
					this.drawPillar(this.selectData, previewGroupCtx);
					// item.dragPoints = this.createPillarControlPoints(item);
				}
				this.drawControlPoints(this.selectData);

				// this.updateAllLayers();
			},

			modData() {
				this.modMainData = this.selectData;
			},
			modConfirm() {
				// lines[this.modMainData.idx] = this.modMainData;
				// this.drawStaticLines();

				// if (this.selectData.type === "line" || this.selectData.type === "arc") {

				// if(Number(this.modMainData.idx)==Number(lines.length-1)){
				this.crosses = [{
					x: lines[lines.length - 1].end.x,
					y: lines[lines.length - 1].end.y,
				}, ];

				this.drawDynamicLayer();
				// }
				lines[this.modMainData.idx] = this.modMainData;
				this.drawStaticLines(); // 重新绘制静态线段
				// }
				this.selectData = this.modMainData;
				this.modMainData = null;
				this.drawSymbol(this.selectData);
				// this.selectData = null
			},

			// 修改墙面材质
			changeWall(type) {
				this.modMainData.wallType = type;
				lines[this.modMainData.idx].wallType = type;
				this.$forceUpdate();
			},
			changeValue(e, key) {
				this.modMainData[key] = e.detail.value;
			},

			// 打开添加
			addItems() {
				this.addItemsShow = true;
				this.selectData = null;
				previewGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				previewGroupCtx.draw(true);
				addItemGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				addItemGroupCtx.draw(true);
				this.drawAddItem();
			},
			// 修改后的计算方法：使用简单平均求几何中心
			calculatePolygonCenter(segments) {
				if (!segments || segments.length === 0) return null;

				// 收集所有不重复的顶点
				const vertices = [];
				const pointSet = new Set();

				segments.forEach((seg) => {
					const startKey = `${seg.start.x},${seg.start.y}`;
					const endKey = `${seg.end.x},${seg.end.y}`;

					if (!pointSet.has(startKey)) {
						pointSet.add(startKey);
						vertices.push(seg.start);
					}
					if (!pointSet.has(endKey)) {
						pointSet.add(endKey);
						vertices.push(seg.end);
					}
				});

				if (vertices.length === 0) return null;

				// 计算几何中心（所有顶点坐标的平均值）
				const sum = vertices.reduce(
					(acc, point) => {
						return {
							x: acc.x + point.x,
							y: acc.y + point.y,
						};
					}, {
						x: 0,
						y: 0,
					}
				);

				return {
					x: sum.x / vertices.length,
					y: sum.y / vertices.length,
				};
			},
			// 面积计算
			calculatePolygonArea(segments) {
				// 1. 按顺序收集所有顶点（确保正确的多边形顶点顺序）
				const vertices = [];

				// 简单处理：假设线段是首尾相连的
				if (segments.length === 0)
					return {
						area: 0,
						centroid: null,
					};

				// 起始点
				vertices.push(segments[0].start);
				vertices.push(segments[0].end);

				// 按顺序连接线段
				for (let i = 1; i < segments.length; i++) {
					const lastPoint = vertices[vertices.length - 1];
					const currentSeg = segments[i];

					// 检查哪一端与上一个点连接
					if (
						distance(lastPoint, currentSeg.start) <
						distance(lastPoint, currentSeg.end)
					) {
						vertices.push(currentSeg.end);
					} else {
						vertices.push(currentSeg.start);
					}
				}

				// 2. 计算面积和质心
				let area = 0;
				let centroidX = 0;
				let centroidY = 0;
				const n = vertices.length;

				for (let i = 0; i < n; i++) {
					const j = (i + 1) % n;
					const xi = vertices[i].x;
					const yi = vertices[i].y;
					const xj = vertices[j].x;
					const yj = vertices[j].y;

					const cross = xi * yj - xj * yi;
					area += cross;

					centroidX += (xi + xj) * cross;
					centroidY += (yi + yj) * cross;
				}

				area = Math.abs(area) / 2;

				if (area === 0)
					return {
						area: 0,
						centroid: null,
					};

				const centroid = {
					x: centroidX / (6 * area),
					y: centroidY / (6 * area),
				};

				return {
					area,
					centroid,
					vertices, // 返回顶点用于调试
				};
			},

			// 绘制门的方法
			// 绘制门的方法（支持单开门和双开门）
			drawDoor(data, ctx) {
				const scalePix = (this.defaultScale / this.viewport.scale) || 1
				ctx.clearRect(0, 0, wxdata.window, wxdata.windowHeight);
				ctx.draw(true);
				const {
					pos,
					wall,
					type = 1
				} = data; // 默认为单开门(type=1)

				// 转换为屏幕坐标
				const screenPos = this.worldToScreen(pos);

				// 门的基本参数
				const doorWidth = data.width / scalePix; // 单扇门宽度(像素)
				const doorThickness = 2; // 门厚度(像素)
				const arcRadius = doorWidth; // 弧线半径

				// 保存当前绘图状态
				ctx.save();

				// 移动到门的位置
				ctx.translate(screenPos.x, screenPos.y);

				// 应用旋转（如果有）
				if (data.rotateDeg) {
					ctx.rotate((data.rotateDeg * Math.PI) / 180);
				}

				// 如果有墙体信息，则根据墙体方向调整
				if (wall) {
					const wallStart = this.worldToScreen(wall.start);
					const wallEnd = this.worldToScreen(wall.end);
					const wallAngle = Math.atan2(
						wallEnd.y - wallStart.y,
						wallEnd.x - wallStart.x
					);

					// 旋转到墙体方向
					ctx.rotate(wallAngle);
					data.rotateDeg = parseInt(wallAngle * (180 / Math.PI));
					if (data.rotateDeg < 0) {
						data.rotateDeg += 360;
					}
				}

				// 绘制门板(矩形)
				ctx.setStrokeStyle("#333");
				ctx.setLineWidth(doorThickness);

				if (type === 1) {
					// 单开门
					ctx.beginPath();
					ctx.moveTo(0, 0);
					ctx.lineTo(doorWidth, 0);
					ctx.stroke();

					// 绘制门开启方向的弧线
					ctx.setLineWidth(2);
					ctx.beginPath();
					ctx.arc(0, 0, arcRadius, -Math.PI / 2, 0, false);
					ctx.stroke();
				} else if (type === 2) {
					// 双开门
					const halfWidth = doorWidth / 2;

					// 左侧门扇
					ctx.beginPath();
					ctx.moveTo(-halfWidth, 0);
					ctx.lineTo(0, 0);
					ctx.stroke();

					// 右侧门扇
					ctx.beginPath();
					ctx.moveTo(0, 0);
					ctx.lineTo(halfWidth, 0);
					ctx.stroke();

					// 绘制双开门开启方向的弧线
					ctx.setLineWidth(2);

					// 左侧门弧线
					ctx.beginPath();
					ctx.arc(halfWidth, 0, halfWidth, Math.PI, (Math.PI * 3) / 2, false);
					ctx.stroke();

					// 右侧门弧线
					ctx.beginPath();
					ctx.arc(-halfWidth, 0, halfWidth, -Math.PI / 2, 0, false);
					ctx.stroke();

					// 绘制左右门楣
					ctx.beginPath();
					ctx.moveTo(-halfWidth, 0);
					ctx.lineTo(-halfWidth, -halfWidth);
					ctx.stroke();

					ctx.beginPath();
					ctx.moveTo(halfWidth, 0);
					ctx.lineTo(halfWidth, -halfWidth);
					ctx.stroke();
				}

				// 绘制门轴小圆点
				ctx.beginPath();
				ctx.arc(0, 0, 3, 0, Math.PI * 2);
				ctx.fill();

				if (type === 2) {
					// 双开门的第二个门轴
					const halfWidth = doorWidth / 2;
					ctx.beginPath();
					ctx.arc(halfWidth, 0, 3, 0, Math.PI * 2);
					ctx.fill();

					ctx.beginPath();
					ctx.arc(-halfWidth, 0, 3, 0, Math.PI * 2);
					ctx.fill();
				}

				// 恢复绘图状态
				ctx.restore();
				ctx.draw(true);
			},


			drawDoorSizeLine(item, ctx) {
				addItemGroupCtx.save();
				const centerPos = this.worldToScreen(item.pos);
				if (item.type == 2) {
					addItemGroupCtx.translate(centerPos.x, centerPos.y);
				} else {
					addItemGroupCtx.translate(centerPos.x + item.width / 2, centerPos.y);
				}

				let rotation = item.rotateDeg || 0;
				if (rotation === 360) rotation = 0;
				addItemGroupCtx.rotate((rotation * Math.PI) / 180);

				const width = item.width;
				const text = `${width} mm`;

				// Calculate annotation position (below when rotation=0)
				const lineOffset = rotation === 0 ? 20 : -20; // Below when unrotated, above when rotated
				const textOffset = rotation === 0 ? 30 : -30;

				// Draw dimension line
				addItemGroupCtx.setStrokeStyle("red");
				addItemGroupCtx.setLineWidth(1);
				addItemGroupCtx.beginPath();

				addItemGroupCtx.moveTo(-width / 2, lineOffset);
				addItemGroupCtx.lineTo(width / 2, lineOffset);
				addItemGroupCtx.stroke();

				// Draw text
				addItemGroupCtx.setFontSize(12);
				addItemGroupCtx.setFillStyle("red");
				addItemGroupCtx.textAlign = "center";
				addItemGroupCtx.textBaseline = rotation === 0 ? "top" : "bottom";
				addItemGroupCtx.fillText(text, 0, textOffset);

				addItemGroupCtx.restore();
				addItemGroupCtx.draw(true)
			},
			// 窗尺寸标注
			drawWindowSizeLine(item, ctx) {
				addItemGroupCtx.save();
				const centerPos = this.worldToScreen(item.pos);
				addItemGroupCtx.translate(centerPos.x, centerPos.y);

				let rotation = item.rotateDeg || 0;
				if (rotation === 360) rotation = 0;
				addItemGroupCtx.rotate((rotation * Math.PI) / 180);

				const width = item.width;
				const height = item.height;

				// Width annotation (below when rotation=0 or 180, above when 90 or 270)
				const widthLineOffset = (rotation === 0 || rotation === 180) ? 20 : -20;
				const widthTextOffset = (rotation === 0 || rotation === 180) ? 30 : -30;

				addItemGroupCtx.setStrokeStyle("red");
				addItemGroupCtx.setLineWidth(1);
				addItemGroupCtx.beginPath();
				addItemGroupCtx.moveTo(-width / 2, widthLineOffset);
				addItemGroupCtx.lineTo(width / 2, widthLineOffset);
				addItemGroupCtx.stroke();

				addItemGroupCtx.setFontSize(12);
				addItemGroupCtx.setFillStyle("red");
				addItemGroupCtx.textAlign = "center";
				addItemGroupCtx.textBaseline = (rotation === 0 || rotation === 180) ? "top" : "bottom";
				addItemGroupCtx.fillText(`${width} mm`, 0, widthTextOffset);

				// Height annotation (right when rotation=0 or 180, left when 90 or 270)
				const heightLineOffset = (rotation === 0 || rotation === 180) ? width / 2 + 10 : -width / 2 - 10;
				const heightTextOffset = (rotation === 0 || rotation === 180) ? width / 2 + 20 : -width / 2 - 20;

				addItemGroupCtx.beginPath();
				addItemGroupCtx.moveTo(heightLineOffset, -height / 2);
				addItemGroupCtx.lineTo(heightLineOffset, height / 2);
				addItemGroupCtx.stroke();

				addItemGroupCtx.textBaseline = "middle";
				addItemGroupCtx.textAlign = (rotation === 0 || rotation === 180) ? "left" : "right";
				addItemGroupCtx.fillText(`${height} mm`, heightTextOffset, 0);

				addItemGroupCtx.restore();
				addItemGroupCtx.draw(true)
			},
			// 柱尺寸标注
			drawPillarSizeLine(pillar, ctx) {
				const that = this;
				const center = this.worldToScreen(pillar.pos);

				if (pillar.type === 1) {
					// 方柱标注
					const width = pillar.width;
					const height = pillar.height;

					// 宽度标注
					addItemGroupCtx.setStrokeStyle("#9933CC");
					addItemGroupCtx.beginPath();
					addItemGroupCtx.moveTo(center.x - width / 2, center.y - height / 2 - 15);
					addItemGroupCtx.lineTo(center.x + width / 2, center.y - height / 2 - 15);
					addItemGroupCtx.stroke();

					addItemGroupCtx.setFontSize(12);
					addItemGroupCtx.setFillStyle("#9933CC");
					addItemGroupCtx.textAlign = "center";
					addItemGroupCtx.fillText(`${width}mm`, center.x, center.y - height / 2 - 20);

					// 高度标注
					addItemGroupCtx.beginPath();
					addItemGroupCtx.moveTo(center.x + width / 2 + 15, center.y - height / 2);
					addItemGroupCtx.lineTo(center.x + width / 2 + 15, center.y + height / 2);
					addItemGroupCtx.stroke();

					addItemGroupCtx.save();
					addItemGroupCtx.translate(center.x + width / 2 + 20, center.y);
					addItemGroupCtx.rotate(Math.PI / 2);
					addItemGroupCtx.textAlign = "center";
					addItemGroupCtx.fillText(`${height}mm`, 0, 0);
					addItemGroupCtx.restore();
				} else {
					// 圆柱标注
					const diameter = pillar.width;

					addItemGroupCtx.setStrokeStyle("#9933CC");
					addItemGroupCtx.beginPath();
					addItemGroupCtx.arc(center.x, center.y, diameter / 2 + 10, 0, Math.PI * 2);
					addItemGroupCtx.stroke();

					// 直径标注
					addItemGroupCtx.beginPath();
					addItemGroupCtx.moveTo(center.x - diameter / 2, center.y - diameter / 2 - 25);
					addItemGroupCtx.lineTo(center.x + diameter / 2, center.y - diameter / 2 - 25);
					addItemGroupCtx.stroke();

					addItemGroupCtx.setFontSize(12);
					addItemGroupCtx.setFillStyle("#9933CC");
					addItemGroupCtx.textAlign = "center";
					addItemGroupCtx.fillText(`${diameter}mm`, center.x, center.y - diameter / 2 - 30);
				}
				addItemGroupCtx.draw(true)
			},
			drawWindow(data, ctx) {
				ctx.clearRect(0, 0, wxdata.window, wxdata.windowHeight);
				ctx.draw(true);
				const scalePix = (this.defaultScale / this.viewport.scale) || 1
				let {
					pos,
					width,
					height,
					wall
				} = data;
				width = width / scalePix
				height = height / scalePix
				// 转换为屏幕坐标
				const screenPos = this.worldToScreen(pos);

				// 保存当前绘图状态
				ctx.save();
				if (data.rotateDeg) {
					ctx.translate(screenPos.x, screenPos.y);
					ctx.rotate((data.rotateDeg * Math.PI) / 180);
					ctx.translate(-screenPos.x, -screenPos.y);
				}
				// 如果有墙体信息，则根据墙体方向调整
				if (wall) {
					const wallStart = this.worldToScreen(wall.start);
					const wallEnd = this.worldToScreen(wall.end);
					const wallAngle = Math.atan2(
						wallEnd.y - wallStart.y,
						wallEnd.x - wallStart.x
					);

					// 移动到窗户位置并旋转到墙体方向
					ctx.translate(screenPos.x, screenPos.y);
					ctx.rotate(wallAngle);

					// 绘制外框矩形
					ctx.setStrokeStyle("#333");
					ctx.setLineWidth(1);
					ctx.strokeRect(-width / 2, -height / 2, width, height);

					// 绘制内部横线
					ctx.beginPath();
					ctx.moveTo(-width / 2, -height / 4);
					ctx.lineTo(width / 2, -height / 4);
					ctx.stroke();

					ctx.beginPath();
					ctx.moveTo(-width / 2, height / 4);
					ctx.lineTo(width / 2, height / 4);
					ctx.stroke();
				} else {
					// 没有墙体信息时默认绘制
					ctx.setStrokeStyle("#333");
					ctx.setLineWidth(1);
					ctx.strokeRect(
						screenPos.x - width / 2,
						screenPos.y - height / 2,
						width,
						height
					);

					ctx.beginPath();
					ctx.moveTo(screenPos.x - width / 2, screenPos.y - height / 4);
					ctx.lineTo(screenPos.x + width / 2, screenPos.y - height / 4);
					ctx.stroke();

					ctx.beginPath();
					ctx.moveTo(screenPos.x - width / 2, screenPos.y + height / 4);
					ctx.lineTo(screenPos.x + width / 2, screenPos.y + height / 4);
					ctx.stroke();
				}

				// 恢复绘图状态
				ctx.restore();
				ctx.draw(true);
			},

			drawPillar(data, ctx) {
				const scalePix = (this.defaultScale / this.viewport.scale) || 1
				// 转换为屏幕坐标
				const screenPos = this.worldToScreen({
					x: data.pos.x,
					y: data.pos.y,
				});
				ctx.beginPath();
				if (data.type == 2) {
					// 绘制圆形
					ctx.arc(screenPos.x, screenPos.y, data.width / scalePix / 2, 0, Math.PI * 2);
				} else {
					// 绘制正方形
					ctx.rect(
						screenPos.x - data.width / scalePix / 2,
						screenPos.y - data.height / scalePix / 2,
						data.width / scalePix,
						data.height / scalePix
					);
				}
				ctx.fillStyle = "#ccc";
				ctx.fill();
				ctx.draw(true);
			},

			convertToArc() {
				if (!this.selectData) return;

				// 计算控制点 - 简单实现: 取线段中点并垂直偏移
				const midPoint = {
					x: (this.selectData.start.x + this.selectData.end.x) / 2,
					y: (this.selectData.start.y + this.selectData.end.y) / 2,
				};

				// 计算垂直方向
				const dx = this.selectData.end.x - this.selectData.start.x;
				const dy = this.selectData.end.y - this.selectData.start.y;

				// 垂直向量 (交换x,y并取负其中一个)
				const perp = {
					x: -dy,
					y: dx,
				};
				const len = Math.sqrt(perp.x * perp.x + perp.y * perp.y);

				// 归一化并缩放
				const scale = distance(this.selectData.start, this.selectData.end) * 0.3; // 曲率系数
				const offset = {
					x: (perp.x / len) * scale,
					y: (perp.y / len) * scale,
				};

				// 更新线段为弧线
				this.selectData.type = "arc";
				this.selectData = {
					...this.selectData,
					type: "arc",
					controlPoint: {
						x: midPoint.x + offset.x,
						y: midPoint.y + offset.y,
					},
				};

				this.drawSymbol(this.selectData);
			},

			convertToLine() {
				if (!this.selectData) return;
				this.selectData.type = "line";
				// 将弧线转回直线
				this.selectData = {
					...this.selectData,
					type: "line",
					controlPoint: null,
				};

				// this.updateAllLayers();
				this.drawSymbol(this.selectData);
			},

			handleAddItemStart(e, classType, data) {
				e.preventDefault();
				this.addData = {
					classType,
					data
				};
				const that = this;

				const touchPos = this.screenToWorld({
					x: e.touches[0].pageX,
					y: e.touches[0].pageY,
				});
				this.touchmoveAll(e);
				// if (classType == "door") {
				// 	addDoorPos = {
				// 		pos: this.snapToGrid(touchPos.x, touchPos.y),

				// 		...data,
				// 	};
				// 	// this.drawDoor(addDoorPos)
				// } else if (classType == "window") {
				// 	addWindowPos = {
				// 		pos: this.snapToGrid(touchPos.x, touchPos.y),

				// 		...data,
				// 	};
				// } else if (classType == "pillar") {
				// 	addPillarPos = {
				// 		pos: this.snapToGrid(touchPos.x, touchPos.y),

				// 		...data,
				// 	};
				// }
			},

			handleAddItemMove(e, classType, data) {
				const that = this;
				if (!rafPending) {
					rafPending = true;
					this.requestAnimFrame(() => {
						const touchPos = this.screenToWorld({
							x: e.touches[0].pageX,
							y: e.touches[0].pageY,
						});
						// 查找最近的墙体
						const closestWall = this.findClosestWall(touchPos);
						const snapPos = closestWall ? closestWall.point : touchPos;
						previewGroupCtx.clearRect(
							0,
							0,
							wxdata.windowWidth,
							wxdata.windowHeight
						);
						if (classType == "door") {
							addDoorPos = {
								...data,
								pos: that.snapToGrid(snapPos.x, snapPos.y),
								idx: doors.length,
								isSelected: false,
								class: "door",

								// wall: closestWall ? closestWall.wall : null,
							};
							if (closestWall) {
								const wallStart = this.worldToScreen(closestWall.wall.start);
								const wallEnd = this.worldToScreen(closestWall.wall.end);
								const wallAngle = Math.atan2(
									wallEnd.y - wallStart.y,
									wallEnd.x - wallStart.x
								);
								addDoorPos.rotateDeg = parseInt(wallAngle * (180 / Math.PI));
								if (addDoorPos.rotateDeg < 0) {
									addDoorPos.rotateDeg += 360;
								}
							}
							if (data.type == 1) {
								addDoorPos.dragPoints = [{
										...that.snapToGrid(touchPos.x, touchPos.y),
										type: "size",
									}, // 尺寸控制点
									{
										...that.snapToGrid(
											touchPos.x + data.width / that.viewport.scale,
											touchPos.y
										),
										type: "size",
									},
								];
							} else if (data.type == 2) {
								addDoorPos.dragPoints = [{
										...that.snapToGrid(
											touchPos.x - data.width / that.viewport.scale / 2,
											touchPos.y
										),
										type: "size",
									},
									{
										...that.snapToGrid(
											touchPos.x + data.width / that.viewport.scale / 2,
											touchPos.y
										),
										type: "size",
									},
								];
							}
						} else if (classType == "window") {
							addWindowPos = {
								...data,
								pos: that.snapToGrid(snapPos.x, snapPos.y),
								width: data.width,
								idx: windowList.length,
								isSelected: false,
								class: "window",
								dragPoints: [{
										...that.snapToGrid(
											touchPos.x - ((1 / 2) * data.width) / that.viewport.scale,
											touchPos.y
										),
										type: "size",
									}, // 尺寸控制点
									{
										...that.snapToGrid(
											touchPos.x + ((1 / 2) * data.width) / that.viewport.scale,
											touchPos.y
										),
										type: "size",
									},
									// {x: x2, y: y2, type: 'move'}   // 移动控制点
								],
								height: closestWall ? closestWall.wall.lineHeight : data.height,
								// wall: closestWall ? closestWall.wall : null,
							};
							if (closestWall) {
								const wallStart = this.worldToScreen(closestWall.wall.start);
								const wallEnd = this.worldToScreen(closestWall.wall.end);
								const wallAngle = Math.atan2(
									wallEnd.y - wallStart.y,
									wallEnd.x - wallStart.x
								);
								addWindowPos.rotateDeg = parseInt(wallAngle * (180 / Math.PI));
								if (addWindowPos.rotateDeg < 0) {
									addWindowPos.rotateDeg += 360;
								}
							}
						} else if (classType == "pillar") {
							// if(data.type==1){
							addPillarPos = {
								pos: that.snapToGrid(snapPos.x, snapPos.y),
								idx: pillarList.length,
								isSelected: false,
								class: "pillar",

								...data,
							};
							if (closestWall) {
								const wallStart = this.worldToScreen(closestWall.wall.start);
								const wallEnd = this.worldToScreen(closestWall.wall.end);
								const wallAngle = Math.atan2(
									wallEnd.y - wallStart.y,
									wallEnd.x - wallStart.x
								);
								addPillarPos.rotateDeg = parseInt(wallAngle * (180 / Math.PI));
								if (addPillarPos.rotateDeg < 0) {
									addPillarPos.rotateDeg += 360;
								}
							}
							if (data.type == 1) {
								addPillarPos.dragPoints = [{
										...that.snapToGrid(
											touchPos.x - ((1 / 2) * data.width) / that.viewport.scale,
											touchPos.y
										),
										type: "size",
										direct: 1,
									}, // 尺寸控制点

									{
										...that.snapToGrid(
											touchPos.x + ((1 / 2) * data.width) / that.viewport.scale,
											touchPos.y
										),
										type: "size",
										direct: 2,
									},
									{
										...that.snapToGrid(
											touchPos.x,
											touchPos.y + ((1 / 2) * data.height) / that.viewport.scale
										),
										type: "size",
										direct: 3,
									},
									{
										...that.snapToGrid(
											touchPos.x,
											touchPos.y - ((1 / 2) * data.height) / that.viewport.scale
										),
										type: "size",
										direct: 4,
									},
									// {x: x2, y: y2, type: 'move'}   // 移动控制点
								];
							} else if (data.type == 2) {
								addPillarPos.dragPoints = [{
										...that.snapToGrid(
											touchPos.x - ((1 / 2) * data.width) / that.viewport.scale,
											touchPos.y
										),
										type: "size",
										direct: 1,
									}, // 尺寸控制点

									{
										...that.snapToGrid(
											touchPos.x + ((1 / 2) * data.width) / that.viewport.scale,
											touchPos.y
										),
										type: "size",
										direct: 2,
									},
									{
										...that.snapToGrid(
											touchPos.x,
											touchPos.y + ((1 / 2) * data.width) / that.viewport.scale
										),
										type: "size",
										direct: 3,
									},
									{
										...that.snapToGrid(
											touchPos.x,
											touchPos.y - ((1 / 2) * data.width) / that.viewport.scale
										),
										type: "size",
										direct: 4,
									},
									// {x: x2, y: y2, type: 'move'}   // 移动控制点
								];
							}
						}
						if (addDoorPos) {
							this.drawDoor(addDoorPos, previewGroupCtx);
						}

						if (addWindowPos) {
							this.drawWindow(addWindowPos, previewGroupCtx);
						}
						if (addPillarPos) {
							this.drawPillar(addPillarPos, previewGroupCtx);
						}
						// this.drawDynamicLayer(); // 实时更新预览
						rafPending = false;
					});
				}
			},

			handleAddItemEnd(e, classType, type) {
				if (!this.addData && this.addData != null) {
					return;
				}
				if (classType == "door") {
					doors.push(addDoorPos);

					this.drawDoor(addDoorPos, addItemGroupCtx);
					this.drawDoorSizeLine(addDoorPos);
					addDoorPos = null;
				} else if (classType == "window") {
					windowList.push(addWindowPos);
					this.drawWindow(addWindowPos, addItemGroupCtx);
					this.drawWindowSizeLine(addWindowPos);
					addWindowPos = null;
				} else if (classType == "pillar") {
					pillarList.push(addPillarPos);
					this.drawPillar(addPillarPos, addItemGroupCtx);
					this.drawPillarSizeLine(addPillarPos);
					addPillarPos = null;
				}
				this.addData = null;
				previewGroupCtx.clearRect(0, 0, wxdata.windowWidth, wxdata.windowHeight);
				previewGroupCtx.draw();
			},

			closestPointOnLine(point, lineStart, lineEnd) {
				const A = point.x - lineStart.x;
				const B = point.y - lineStart.y;
				const C = lineEnd.x - lineStart.x;
				const D = lineEnd.y - lineStart.y;

				const dot = A * C + B * D;
				const len_sq = C * C + D * D;
				let param = -1;

				if (len_sq !== 0) {
					param = dot / len_sq;
				}

				let xx, yy;

				if (param < 0) {
					xx = lineStart.x;
					yy = lineStart.y;
				} else if (param > 1) {
					xx = lineEnd.x;
					yy = lineEnd.y;
				} else {
					xx = lineStart.x + param * C;
					yy = lineStart.y + param * D;
				}

				return {
					point: {
						x: xx,
						y: yy,
					},
					distance: Math.sqrt((point.x - xx) ** 2 + (point.y - yy) ** 2),
				};
			},

			findClosestWall(point) {
				let threshold = 10 / this.viewport.scale;
				let closest = null;
				let minDistance = Infinity;
				let closestPoint = null;

				// 检查所有墙体线段
				const allWalls = [...lines, ...sureRoom.flat()];

				allWalls.forEach((wall) => {
					if (wall.type === "arc" && wall.controlPoint) {
						// 对于弧线墙，使用近似方法 - 将弧线分成多段线段来检测
						const segments = 10;
						let prevPoint = wall.start;

						for (let i = 1; i <= segments; i++) {
							const t = i / segments;
							const currentPoint = {
								x: (1 - t) * (1 - t) * wall.start.x +
									2 * (1 - t) * t * wall.controlPoint.x +
									t * t * wall.end.x,
								y: (1 - t) * (1 - t) * wall.start.y +
									2 * (1 - t) * t * wall.controlPoint.y +
									t * t * wall.end.y,
							};

							const result = this.closestPointOnLine(
								point,
								prevPoint,
								currentPoint
							);
							if (result.distance < minDistance) {
								minDistance = result.distance;
								closest = wall;
								closestPoint = result.point;
							}

							prevPoint = currentPoint;
						}
					} else {
						// 直线墙
						const result = this.closestPointOnLine(point, wall.start, wall.end);
						if (result.distance < minDistance) {
							minDistance = result.distance;
							closest = wall;
							closestPoint = result.point;
						}
					}
				});

				return minDistance <= threshold ? {
						wall: closest,
						point: closestPoint,
					} :
					null;
			},

			// 添加贝塞尔曲线近似检测方法
			isPointNearBezier(point, p0, p1, p2, threshold) {
				// 将曲线分成多段线段来近似检测
				const segments = 20;
				let prevPoint = p0;
				let minDistance = Infinity;

				for (let i = 1; i <= segments; i++) {
					const t = i / segments;
					const currentPoint = {
						x: (1 - t) * (1 - t) * p0.x + 2 * (1 - t) * t * p1.x + t * t * p2.x,
						y: (1 - t) * (1 - t) * p0.y + 2 * (1 - t) * t * p1.y + t * t * p2.y,
					};

					// 计算点到线段的距离
					const lineLength = distance(prevPoint, currentPoint);
					if (lineLength === 0) {
						minDistance = Math.min(minDistance, distance(point, prevPoint));
					} else {
						const t2 = Math.max(
							0,
							Math.min(
								1,
								(point.x - prevPoint.x) * (currentPoint.x - prevPoint.x) +
								((point.y - prevPoint.y) * (currentPoint.y - prevPoint.y)) /
								lineLength ** 2
							)
						);
						const projection = {
							x: prevPoint.x + t2 * (currentPoint.x - prevPoint.x),
							y: prevPoint.y + t2 * (currentPoint.y - prevPoint.y),
						};
						minDistance = Math.min(minDistance, distance(point, projection));
					}

					prevPoint = currentPoint;
				}

				return minDistance <= threshold;
			},
		},
	};
</script>

<style lang="scss">
	body,
	html {
		-webkit-overflow-scrolling: none;
		/* 禁用弹性滚动 */
		touch-action: none;
		/* 禁用触摸默认行为 */
	}

	.engineering-canvas {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		overflow: hidden;
		-webkit-overflow-scrolling: touch;
		/* 禁用弹性滚动 */
		touch-action: none;
		height: 100%;
		z-index: 0;

		/* 禁用触摸默认行为 */
	}

	.canvas-layer {
		position: absolute;
		width: 100vw;
		height: 100vh;
		z-index: 1;
	}

	.data-operate {
		position: absolute;
		right: 20rpx;
		top: 200rpx;
		background: rgba(0, 0, 0, 0.5);
		z-index: 10;
		padding: 10rpx;
		border-radius: 20rpx;

		.ope {
			display: flex;
			flex-direction: column;
			align-items: center;
			font-size: 24rpx;
			color: #fff;
			margin-bottom: 20rpx;

			.ope-icon {
				width: 60rpx;
				height: 60rpx;
				// background:white
			}

			.ope-name {
				margin-top: 5rpx;
			}
		}

		.ope:last-child {
			margin-bottom: 0rpx;
		}
	}

	.data-main-set {
		position: absolute;
		bottom: 0;
		// height: 200rpx;
		width: 100%;
		z-index: 13;
		padding: 30rpx 0 0;
		background: #fff;
		border-radius: 20rpx 20rpx 0 0;
		box-shadow: 0px 0px 12rpx 0px #e3e5e8;
		box-sizing: border-box;

		.status-type-list {
			display: flex;

			.single-status {
				margin: 0 40rpx 40rpx;
			}

			.status-active {
				color: orange;
			}
		}

		.wall-thick {
			// margin: 20rpx 0 0 0;
			padding: 10rpx 0 0;
			width: 100%;
			background: #ccc;

			.wall-thick-input {
				width: 100%;
				padding: 20rpx;
				box-sizing: border-box;
				border: 1rpx solid #ccc;
				border-radius: 10rpx;
				display: flex;
				justify-content: space-between;
				background: #fff;
			}
		}

		.wall-thick-calendar {
			display: flex;
			justify-content: space-between;
			background: #ccc;

			.cal-num {
				// flex:1;
				width: 500rpx;
				display: flex;
				justify-content: flex-start;
				flex-wrap: wrap;

				.single-num {
					width: 33%;
					padding: 10rpx;
					box-sizing: border-box;
					text-align: center;
				}
			}

			.cal-confirm {
				// width:370rpx;

				flex: 1;
				height: 470rpx;
				display: flex;
				flex-direction: column;
				justify-content: flex-start;

				.cal-del {
					padding: 10rpx;
					box-sizing: border-box;
				}

				.cal-sure {
					padding: 10rpx;
					flex: 1;
					box-sizing: border-box;
				}
			}

			.cal-btn {
				padding: 10rpx;
				background: #fff;
				height: 80rpx;
				line-height: 80rpx;
				border-radius: 10rpx;
				display: flex;
				align-items: center;
				justify-content: center;
			}
		}
	}

	.wall-list {
		display: flex;
		justify-content: flex-start;
		flex-wrap: wrap;

		// grid-template-columns: 1fr 1fr 1fr 1fr;

		.wall {
			width: 25%;
			padding: 10rpx;
			box-sizing: border-box;
			position: relative;

			.wallPic {
				width: 100%;
				height: 100rpx;
			}

			.selected-wall {
				position: absolute;
				right: 0;
				top: 0;
				width: 30rpx;
				height: 30rpx;
			}

			.wallDesc {
				text-align: center;
			}
		}

		.active-wall {
			// background: blue;
			border: 1rpx solid #ccc;
			box-sizing: border-box;
		}
	}

	.draw-oprate-btn {
		position: absolute;
		bottom: 300rpx;
		right: 50rpx;
		z-index: 10;

		.close-btn {
			text-align: center;
			line-height: 100rpx;
			color: #fff;
			width: 100rpx;
			height: 100rpx;
			background: orange;
			border-radius: 50%;
		}
	}

	.bot-btn-list {
		width: 100%;
		left: 0;
		touch-action: none;
		// background: orange;
		position: absolute;
		bottom: 50rpx;
		display: flex;
		align-items: flex-start;
		justify-content: flex-end;
		z-index: 9;

		.bot-btn {
			width: 25%;
			// background: orange;
			// margin:0 50rpx;
			display: flex;
			flex-direction: column;
			align-items: center;
			font-size: 16rpx;

			.btn-icon {
				width: 100rpx;
				height: 100rpx;
				text-align: center;
				line-height: 50rpx;
				color: #fff;
				display: block;
				// background: #fff;
				border-radius: 50%;
				margin-bottom: 16rpx;
				height: 100%;
				// padding:15rpx;
				// background:orange
			}
		}
	}

	.add-item-list {
		-webkit-overflow-scrolling: touch;
		touch-action: none;
		overflow: hidden;
		position: absolute;
		box-shadow: 0px 0px 12rpx 0px #e3e5e8;
		bottom: 0;
		width: 100%;
		// height: 300rpx;
		background: #fff;
		box-sizing: border-box;
		z-index: 100;
		padding: 50rpx 0 30rpx 0;
		border-radius: 20rpx 20rpx 0 0;

		.tab-scroll {
			width: 100%;
			margin-bottom: 20rpx;

			.tab-list {
				width: 100%;
				display: flex;
				padding: 0 50rpx;

				.tab-item {
					white-space: nowrap;
					margin-right: 30rpx;
				}

				.active-item {
					color: orange;
					position: relative;
				}

				.active-item:after {
					content: "";
					display: block;
					width: 100%;
					height: 1rpx;
					background: orange;
					left: 0;
					bottom: -20rpx;
				}
			}
		}

		.tab-list {
			width: 100%;
			display: flex;
		}

		.tab-item-main {
			display: flex;
			justify-content: flex-start;
			flex-wrap: wrap;
			padding: 0 50rpx;

			.add-item {
				display: flex;
				width: 25%;
				flex-direction: column;
				align-items: center;
				justify-content: center;
				padding: 10rpx;
				-webkit-tap-highlight-color: transparent;
				-webkit-touch-callout: none;
				user-select: none;

				.add-inner {
					background: rgb(241, 241, 239);
					padding-bottom: 10rpx;

					.add-item-icon {
						width: 100%;
						// height:100rpx;
						padding: 10rpx 10rpx 0;
						box-sizing: border-box;
						// background: #ccc;
					}

					.add-item-name {
						box-sizing: border-box;
						text-align: center;
						width: 100%;
					}
				}
			}
		}
	}
</style>